使用react-admin对接Django REST API遇Content-Range header缺失问题求助
我尝试使用react-admin的ra-data-simple-rest数据提供者请求Django REST API,为此在Django中编写了自定义分页类来返回DataProvider所需的Content-Range响应头,代码如下:
from rest_framework import pagination from rest_framework.response import Response class ContentRangeHeaderPagination(pagination.PageNumberPagination): def get_paginated_response(self, data): total_items = self.page.paginator.count # queryset中的总条目数 item_starting_index = self.page.start_index() - 1 # 页面索引从1开始 item_ending_index = self.page.end_index() - 1 content_range = 'posts: {0}-{1}/{2}'.format(item_starting_index, item_ending_index, total_items) headers = {'Content-Range': content_range} return Response(data, headers=headers)
同时在Django配置中做了如下设置:
INSTALLED_APPS = [ ... 'corsheaders', 'rest_framework', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ] REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': '<myProject>.pagination.ContentRangeHeaderPagination', 'PAGE_SIZE': 10 } CORS_ALLOWED_ORIGINS = [ 'http://127.0.0.1:5173', ] CORS_ALLOW_HEADERS = ( "accept", "range", "content-range", "authorization", "content-type", "user-agent", "x-csrftoken", "x-requested-with", )
但一直收到错误提示:
"The Content-Range header is missing in the HTTP Response. The simple REST data provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?"
由于ra-data-django-rest-framework数据提供者已过时,安装时存在依赖冲突无法使用,请问我哪里配置出错了?
你的问题出在两个关键配置点:
1. CORS未配置暴露Content-Range响应头
CORS_ALLOW_HEADERS控制的是前端可发送给后端的请求头,而错误提示中提到的Access-Control-Expose-Headers才是控制后端允许前端读取的响应头。浏览器默认仅允许前端读取少数安全响应头(如Content-Type),自定义的Content-Range必须显式配置暴露,才能被ra-data-simple-rest正常读取。
在Django的settings.py中添加以下配置:
CORS_EXPOSE_HEADERS = ( "content-range", # 可根据需求添加其他需要暴露的响应头 )
2. Content-Range中的资源名称硬编码,不具备通用性
你当前代码中固定使用posts作为资源名称,这会导致非posts的资源列表请求时,Content-Range格式不符合react-admin的预期(正确格式应为{资源名} {起始索引}-{结束索引}/{总条数},比如users 0-9/100)。可以通过视图的basename动态获取当前请求的资源名称:
修改分页类中content_range的生成代码:
# 获取当前视图对应的资源名称 resource_name = self.request.parser_context.get('view').basename content_range = '{0} {1}-{2}/{3}'.format(resource_name, item_starting_index, item_ending_index, total_items)
这样无论请求哪个资源的列表,Content-Range都会使用正确的资源名称,避免react-admin解析失败。
内容的提问来源于stack exchange,提问作者Peter Kamphausen

