Определить тип запрашиваемого контента?

Я хотел бы написать представление 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 для этого?

Ответы

Ответ 1

HttpRequest.META, более конкретно HttpRequest.META.get('HTTP_ACCEPT') — и не HttpRequest.META.get('CONTENT_TYPE'), как упоминалось ранее

Ответ 2

Заголовок

'Content-Type' указывает на отправку типа медиа в HTTP-запросе. Это используется для запросов, содержащих контент (POST, PUT).

'Content-Type' не должен использоваться для указания предпочтительного формата ответа, для этой цели служит заголовок Accept. Чтобы получить доступ к нему в Django, используйте: HttpRequest.META.get('HTTP_ACCEPT')

Подробнее об этих заголовках см. более подробное описание

Ответ 3

Как сказано в других ответах, эта информация находится в заголовке запроса 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 и Стандартная спецификация качества

Ответ 4

в django 1.10 теперь вы можете использовать request.content_type, как указано здесь, в их документ