Django 中间件如何处理请求和响应的内容协商?

2023-04-11 00:00:00 求和 如何处理 协商

Django 中间件可以用来处理请求和响应的内容协商,即根据请求头部的 Accept 字段和视图函数返回的数据类型,自动选择最合适的响应格式。下面是处理内容协商的中间件代码,以及如何使用:

from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin

class ContentNegotiationMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        if response.exception or response.status_code != 200 or not hasattr(response, 'data'):
            return response

        # 根据请求头部获取客户端能接受的数据类型
        accept_header = request.META.get('HTTP_ACCEPT', '')
        accept_format = self.get_accept_format(accept_header)

        # 如果客户端接受的是 JSON 格式,则将数据转换为 JSON 格式
        if accept_format == 'json':
            response.content = json.dumps(response.data)
            response['Content-Type'] = 'application/json'

        # 如果客户端接受的是 XML 格式,则将数据转换为 XML 格式
        elif accept_format == 'xml':
            response.content = xml.etree.ElementTree.tostring(response.data)
            response['Content-Type'] = 'application/xml'

        return response

    def get_accept_format(self, accept_header):
        """根据请求头部获取客户端能接受的数据类型"""
        if 'application/json' in accept_header:
            return 'json'
        elif 'application/xml' in accept_header:
            return 'xml'
        else:
            return 'json'

上面的中间件代码会根据客户端请求头部的 Accept 字段,自动选择最合适的响应格式,并将数据转换为对应格式的内容。使用该中间件只需要在 MIDDLEWARE 设置中添加该中间件的路径即可,例如:

MIDDLEWARE = [
    # ...
    'myapp.middleware.ContentNegotiationMiddleware',
]

现在,假设我们有一个视图函数 hello_world,返回的数据类型为 Python 字典格式。如果客户端请求头部的 Accept 字段为 application/json,则返回 JSON 格式的数据;如果请求头部为 application/xml,则返回 XML 格式的数据。例如:

from django.http import JsonResponse
from django.shortcuts import render

def hello_world(request):
    data = {'message': 'Hello World!'}
    return JsonResponse(data)

在客户端发送请求时,可以设置请求头部的 Accept 字段来指定期望的响应格式:

$ curl -H 'Accept: application/json' 'http://example.com/hello'
{"message": "Hello World!"}

$ curl -H 'Accept: application/xml' 'http://example.com/hello'
<?xml version="1.0" encoding="UTF-8"?>
<root><message>Hello World!</message></root>

上面的代码演示了客户端发送不同格式的请求,然后服务器自动根据客户端请求头部自动选择最合适的响应格式。

相关文章