Django-上下文必须是字典而不是ReturnList

时间:2020-03-23 15:22:30

标签: django

我正在处理django项目,并且有一个Post模型,该模型具有以下视图:

class PostListApiView(ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    filter_backends = [SearchFilter]
    search_fields = ['user','title','content']

我使用此视图创建新帖子:

@method_decorator(login_required, name='dispatch')
class PostCreateView(APIView):
    queryset = Post.objects.all()
    serializer_class = PostCreateSerializer
    renderer_classes = [TemplateHTMLRenderer]
    permission_classes = [IsAuthenticated]
    template_name = 'post_form.html'

    def get(self, request, format=None):
        serializer=PostCreateSerializer()
        return Response({'serializer':serializer})

    def post(self, request):
        serializer = PostCreateSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'serializer':serializer})
        serializer.save()
        return redirect('/')

我想将两个视图合并为一个视图,

class PostListApiView(ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    filter_backends = [SearchFilter]
    search_fields = ['user','title','content']
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'post_form.html'

但是当我尝试将TemplateHTMLRenderer添加到ListCreateAPIView时,出现此错误:

Traceback (most recent call last):
  File "C:\...\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\...\lib\site-packages\django\core\handlers\base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\...\lib\site-packages\django\core\handlers\base.py", line 143, in _get_response
    response = response.render()
  File "C:\...\lib\site-packages\django\template\response.py", line 105, in render
    self.content = self.rendered_content
  File "C:\...\lib\site-packages\rest_framework\response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "C:\...\lib\site-packages\rest_framework\renderers.py", line 167, in render
    return template.render(context, request=request)
  File "C:\...\lib\site-packages\django\template\backends\django.py", line 59, in render
    context = make_context(context, request, autoescape=self.backend.engine.autoescape)
  File "C:\...\lib\site-packages\django\template\context.py", line 270, in make_context
    raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)

Exception Type: TypeError at /posts/
Exception Value: context must be a dict rather than ReturnList.

我可以使用TemplateHTMLRenderer在模板上呈现查询集和表单吗?如何实现?

谢谢

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题并开始调试 DRF 以试图解决这个问题。 DRF 的序列化器、TemplateHTMLRenderer 和 Django 的模板渲染器之间似乎存在某种问题。

就我而言,我正在尝试使用 ListCreateAPIView 来获得默认的获取和创建行为。我想要 json 和 html 响应,所以尝试了这个代码:

class TransactionsController(ListCreateAPIView):
    queryset = Transaction.objects.all()
    serializer_class = TransactionSerializer
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'transactions/index.html'

当尝试访问交易列表时,尽管返回了以下 DRF 文档:

enter image description here

似乎 django\template\context.py 需要一个 dict,但 DRF 序列化程序返回一个 ReturnList (至少当没有从数据库中检索到数据时)。这个空的 ReturnList 由 TemplateHTMLRenderer 处理,后者又调用 django 渲染器,后者抛出异常。

我目前的快速解决方法是:

from rest_framework.generics import ListCreateAPIView
from rest_framework.renderers import TemplateHTMLRenderer

from applications.core.models.transaction import Transaction, TransactionSerializer


class TransactionsTemplateHTMLRender(TemplateHTMLRenderer):
    def get_template_context(self, data, renderer_context):
        data = super().get_template_context(data, renderer_context)
        if not data:
            return {}
        else:
            return data


class TransactionsController(ListCreateAPIView):
    queryset = Transaction.objects.all()
    serializer_class = TransactionSerializer
    renderer_classes = [TransactionsTemplateHTMLRender]
    template_name = 'transactions/index.html'

这会检查 DRF 的序列化程序返回的数据,如果为空,则返回一个 dict(而不是默认的 ReturnList)。它有效,但现在我们必须看看从数据库中检索实际数据时会发生什么。

我想在 DRF github 上报告这个是个好主意。