2011-09-18 14 views
14

Chciałbym napisać widok Django, który udostępnia treść wariantową w zależności od potrzeb. Na przykład dla "text/xml" podaj XML, dla "text/json", podaj JSON, itp. Czy istnieje sposób na określenie tego z obiektu żądania? Coś takiego byłoby niesamowite:Określić żądany typ zawartości?

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

Czy jest tam nieruchomość pod numerem HttpRequest?

Odpowiedz

10

HttpRequest.META dokładniej HttpRequest.META.get('HTTP_ACCEPT') — i nie HttpRequest.META.get('CONTENT_TYPE') jak wspomniano wcześniej

+4

wiem, że to jest stary, ale mimo to jest akceptowane odpowiedź nie jest poprawna . Jak wspomniano w komentarzu poniżej, poprawną metodą jest nagłówek "Accept", dostępny przez 'HttpRequest.META.get ('HTTP_ACCEPT')'. –

+2

Możesz zrobić rezerwę, aby obsłużyć oba przypadki (plus domyślny): 'request.META.get ('HTTP_ACCEPT', request.META.get ('CONTENT_TYPE', 'application/your_default'))' –

16

nagłówka 'Content-Type' wskazuje typ nośnika wysłać żądanie HTTP. Ta opcja jest używana dla żądań, które mają treść (POST, PUT).

"Content-Type" nie powinien być używany do wskazania preferowanego formatu odpowiedzi, służy do tego nagłówek "Accept". Aby uzyskać do niego dostęp w Django użytku: HttpRequest.META.get („”) HTTP_ACCEPT

See more detailed description of these headers

1

Jak powiedział w innych odpowiedzi, ta informacja znajduje się w nagłówku Accept żądania. Dostępne w żądaniu jako HttpRequest.META['HTTP_ACCEPT'].

Jednak istnieje tylko jeden żądany typ zawartości, a ten nagłówek często jest listą akceptowanych/preferowanych typów zawartości. Ta lista może być nieco denerwująca do prawidłowego wykorzystania. Oto funkcja, która spełnia swoje zadanie:

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

Na przykład, jeśli request.META['HTTP_ACCEPT'] jest równa "text/html;q=0.9,application/xhtml+xml,application/xml;q=0.8,*/*;q=0.7". To powróci: ['application/xhtml+xml', 'text/html', 'application/xml', '*/*'](nie w rzeczywistości, ponieważ zwraca generator).

Następnie można powtórzyć listę wynikową, aby wybrać pierwszy typ zawartości, o którym wiesz, jak poprawnie reagować.

Pamiętaj, że ta funkcja powinna działać w większości przypadków, ale nie obsługuj takich przypadków, jak q=0, co oznacza "Nieakceptowalne".

Źródła: HTTP Accept header specification i Quality Values specification

+0

Ta odpowiedź powinna zastąp najwyższą i zaakceptowaną odpowiedź. – user73657

Powiązane problemy