2011-09-18 93 views
14

我想编写一个Django视图,它根据请求提供不同的内容。例如,对于“text/xml”,提供XML,“text/json”,提供JSON等等。有没有一种方法可以从请求对象中确定?这样的事情会很棒:确定请求的内容类型?

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

有没有这样一个属性HttpRequest

回答

10

HttpRequest.META,更具体地HttpRequest.META.get('HTTP_ACCEPT') —和不 HttpRequest.META.get('CONTENT_TYPE') 如前所述

+4

提到我知道这是旧的,但尽管这是公认的答案,这是不正确的。正如在下面的Jan的评论中提到的,正确的方法是'Accept'标头,可以通过'HttpRequest.META.get('HTTP_ACCEPT')'访问。 –

+2

你可以做一个回退,来处理这两种情况(加上默认值):'request.META.get('HTTP_ACCEPT',request.META.get('CONTENT_TYPE','application/your_default'))' –

16

'的Content-Type' 报头指示媒体类型在HTTP请求发送。这用于具有内容的请求(POST,PUT)。

'内容类型'不应该用来表示首选的响应格式,'接受'标题用于此目的。访问它在Django使用:HttpRequest.META.get(“HTTP_ACCEPT”)

See more detailed description of these headers

1

如所述在其他的答案,该信息位于Accept请求报头。请求中可用HttpRequest.META['HTTP_ACCEPT']

但是,不仅有一个请求的内容类型,并且这个头部通常是接受/首选内容类型的列表。这个列表可能有点讨厌正确利用。下面是做这项工作的函数:

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)) 

举例来说,如果request.META['HTTP_ACCEPT']等于"text/html;q=0.9,application/xhtml+xml,application/xml;q=0.8,*/*;q=0.7"。这将返回:['application/xhtml+xml', 'text/html', 'application/xml', '*/*'](实际上不是,因为它返回一个发电机)

然后,您可以遍历结果列表以选择您知道如何正确响应的第一个内容类型。

请注意,此功能应适用于大多数情况,但不处理诸如q=0这意味着“不可接受”的情况。

来源:HTTP Accept header specificationQuality Values specification

+0

这个答案应该替换顶部并接受答案。 – user73657

1
在Django 1.10

,你现在可以使用,request.content_type,因为在这里their doc

相关问题