2011-09-18 9 views
14

Me gustaría escribir una vista de Django que muestre el contenido de la variante según lo que se solicite. Por ejemplo, para "text/xml", servir XML, para "text/json", servir JSON, etc. ¿Hay alguna manera de determinar esto desde un objeto de solicitud? Algo como esto sería impresionante:¿Determina el tipo de contenido solicitado?

def process(request): 
    if request.type == "text/xml": 
     pass 
    elif request.type == "text/json": 
     pass 
    else: 
     pass 

¿Hay una propiedad en HttpRequest para esto?

Respuesta

10

HttpRequest.META, más específicamente HttpRequest.META.get('HTTP_ACCEPT') — y no HttpRequest.META.get('CONTENT_TYPE') como se mencionó anteriormente

+4

Sé que esto es viejo, pero aunque esta es la respuesta aceptada, no es correcto . Como se menciona en el comentario de Jan a continuación, el método correcto es el encabezado 'Aceptar', accesible a través de 'HttpRequest.META.get ('HTTP_ACCEPT')'. –

+2

Podría hacer un repliegue, para manejar ambos casos (más un valor predeterminado): 'request.META.get ('HTTP_ACCEPT', request.META.get ('CONTENT_TYPE', 'application/your_default'))' –

16

encabezado 'Content-Type' indica el tipo de medio en enviar la petición HTTP. Esto se usa para solicitudes que tienen un contenido (POST, PUT).

'Content-Type' no se debe utilizar para indicar el formato de respuesta preferido; el encabezado 'Aceptar' sirve para este fin. Para acceder a ella en el uso de Django: HttpRequest.META.get ('HTTP_ACCEPT')

See more detailed description of these headers

1

Como se ha dicho en otras respuestas, esta información se encuentra en la cabecera Accept petición. Disponible en la solicitud como HttpRequest.META['HTTP_ACCEPT'].

Sin embargo, no hay un solo tipo de contenido solicitado, y este encabezado a menudo es una lista de tipos de contenido aceptado/preferido. Esta lista puede ser un poco molesta para explotar correctamente. Aquí es una función que hace el trabajo:

import re 

def get_accepted_content_types(request): 
    def qualify(x): 
     parts = x.split(';', 1) 
     if len(parts) == 2: 
      match = re.match(r'(^|;)q=(0(\.\d{,3})?|1(\.0{,3})?)(;|$)', 
          parts[1]) 
      if match: 
       return parts[0], float(match.group(2)) 
     return parts[0], 1 

    raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') 
    qualified_content_types = map(qualify, raw_content_types) 
    return (x[0] for x in sorted(qualified_content_types, 
           key=lambda x: x[1], reverse=True)) 

Por ejemplo, si request.META['HTTP_ACCEPT'] es igual a "text/html;q=0.9,application/xhtml+xml,application/xml;q=0.8,*/*;q=0.7". Esto devolverá: ['application/xhtml+xml', 'text/html', 'application/xml', '*/*'](no en realidad, ya que devuelve un generador).

Luego puede recorrer la lista resultante para seleccionar el primer tipo de contenido que sabe cómo responder correctamente.

Tenga en cuenta que esta función debería funcionar para la mayoría de los casos pero no para casos como q=0 que significa "No aceptable".

Fuentes: HTTP Accept header specification y Quality Values specification

+0

Esta respuesta debería reemplace la respuesta superior y aceptada. – user73657

1

en Django 1.10, ahora se puede utilizar, request.content_type, como se ha mencionado aquí en their doc

Cuestiones relacionadas