【问题标题】:Error when creating a custom response message创建自定义响应消息时出错
【发布时间】:2018-02-01 12:51:39
【问题描述】:

我想实现一个电子邮件验证系统,我让它工作的方式看起来很“老套”,但它似乎运作良好。

我在函数的返回部分创建了一个自定义响应,但我不断收到以下错误:

The response content must be rendered before it can be iterated over.

这个过程是标准的:有人注册,当我去保存用户模型时,我有一个send_mail() 函数,它发送带有验证密钥的电子邮件。用户点击链接,它会像这样传递密钥:

/api/account/verify/849c40665175e56709855cc7aec2b16c05a4d977b3b083790334c6bc01f6e522

在视图中,您可以看到我从哪里拔出钥匙并处理所有内容。我猜这个错误是因为我在get_queryset() 中使用了Response(),但我不确定。如果没有,如何创建自定义响应消息?

版本

Python==2.7.10
Django==1.11.4
djangorestframework==3.6.3

型号

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), null=False, unique=True)
    first_name = models.TextField(_('first name'), null=False)
    last_name = models.TextField(_('last name'), null=False)
    is_active = models.BooleanField(_('active'), default=False)
    is_admin = models.BooleanField(_('admin'), default=False)
    created_on = models.DateTimeField(_('create on'), auto_now_add=True)
    updated_on = models.DateTimeField(_('updated on'), auto_now=True)
    is_staff = models.BooleanField(_('staff'), default=False)
    activation_key = models.CharField(_('email validation key'), default='', max_length=256)

查看

class ActivateViewSet(generics.ListAPIView):

    queryset = User.objects
    serializer_class = ActivationSerializer

    def get_queryset(self):
        activation_key = self.kwargs['activation_key']
        if User.objects.all().filter(activation_key=activation_key).exists():
            User.objects.all().filter(activation_key=activation_key).update(is_active=True)
            return Response({'message': 'key accepted'}, status=status.HTTP_204_NO_CONTENT)
        raise NotFound('activation key not found')

序列化器

class ActivationSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('email',)

追溯

File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
  41.response = get_response(request)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  187.response = self.process_exception_by_middleware(e, request)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  185.response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.return view_func(*args, **kwargs)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/django/views/generic/base.py" in view
  68.return self.dispatch(request, *args, **kwargs)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  489.response = self.handle_exception(exc)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/views.py" in handle_exception
  449.self.raise_uncaught_exception(exc)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  486.response = handler(request, *args, **kwargs)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/generics.py" in get
  201.return self.list(request, *args, **kwargs)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/mixins.py" in list
  48.return Response(serializer.data)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/serializers.py" in data
  739.ret = super(ListSerializer, self).data
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/serializers.py" in data
  263.self._data = self.to_representation(self.instance)
File "/Users/*/.virtualenvs/video_env/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  657.self.child.to_representation(item) for item in iterable
File "/Users/*y/.virtualenvs/video_env/lib/python2.7/site-packages/django/template/response.py" in __iter__
  121.'The response content must be rendered before it can be iterated over.'

Exception Type: ContentNotRenderedError at /api/account/activate/849c40665175e56709855cc7aec2b16c05a4d977b3b083790334c6bc01f6e522/
Exception Value: The response content must be rendered before it can be iterated over.

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    get_queryset 期望返回类型是 queryset 而不是 Response 对象。您需要将代码更改为类似

    def get_queryset(self):
            activation_key = self.kwargs['activation_key']
            if User.objects.all().filter(activation_key=activation_key).exists():
                users = User.objects.all().filter(activation_key=activation_key)
                                          .update(is_active=True)
                return user
    

    现在,由于您想发送自定义响应,因此无法在 get_queryset 中完成。您必须覆盖序列化程序的 create 方法。下面是如何覆盖它的一般示例。

    def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            if not serializer.is_valid(raise_exception=False):
                return Response({"Fail": "blablal", status=status.HTTP_400_BAD_REQUEST)
    
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            return Response({"Success": "msb blablabla"}, status=status.HTTP_201_CREATED, headers=headers)
    

    【讨论】:

    • 感谢您的反馈。我有点想用get_queryset() 发送自定义响应是问题所在。我确实有一个问题;因为我使用的是GET,所以创建仍然有效吗?我对 Django 很陌生,但我发现 Django 有很多“魔法”。当我使用create() 时,会使用GET 方法触发吗?
    • create 适用于各种请求,因为它是为请求创建响应的方法。
    • 啊,不知道:)
    • 你好@Mike你能告诉我你是如何让它工作的吗?提前致谢
    猜你喜欢
    • 2018-11-13
    • 1970-01-01
    • 2019-10-07
    • 2012-02-16
    • 1970-01-01
    • 2021-10-29
    • 2016-07-10
    • 2014-07-29
    • 1970-01-01
    相关资源
    最近更新 更多