【问题标题】:Django rest framework disable field update after conditionDjango rest框架在条件后禁用字段更新
【发布时间】:2014-11-25 20:08:00
【问题描述】:

我正在使用 DRF,如果符合同一模型的条件,我需要禁用字段更新。

示例:

class Foo(models.Model):
    text = models.CharField()
    checkfield = models.BooleanField(default=False)

text 可以修改,除非checkfieldTrue

所以 if Foo.checkfield is True Foo.text 不能通过 DRF API 修改。 最好的方法是什么?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    我认为Advanced serializers 会做你想做的事。

    只需创建您的自定义序列化程序,然后在您的视图中检查校验字段的值。如果为真,则将文本参数传递给它,以便在序列化程序中启用该字段。

    顺便说一句,由于您只需要删除或添加一个固定的额外字段,而不是像示例中那样传递 fields 参数,您可以传递类似 enable_text=checkfield 的内容,然后将文本字段添加到“字段”根据'checkfield'的值在你的序列化器中变量。

    更新澄清:

    定义没有文本字段的序列化程序。然后在您的 ModelViewSet 中,覆盖更新方法,以便您以这种方式获取序列化程序(我认为 get_serializer() 方法不允许传递额外的参数):

    YourSerializer(object, enable_text=True)

    并且,在您的序列化器 init 方法中,当 'enable_text' 为 True 时,您将文本字段添加到 self.fields 属性。

    我没有测试这是否有效,但我认为这是要走的路。

    使用 sn-p 编辑和修改

    我一直在挖掘我所解释的内容,结果发现对于您尝试进行的简单修改来说有点混乱。我想出的只是覆盖 ViewSet 中的更新方法。代码如下:

    from rest_framework import viewsets, status
    from rest_framework.response import Response
    from models import Test, TestSerializer
    
    
    class TestViewSet(viewsets.ModelViewSet):
        queryset = Test.objects.all()
        serializer_class = TestSerializer
    
        def update(self, request, *args, **kwargs):
            partial = kwargs.pop('partial', False)
            self.object = self.get_object_or_none()
    
            if 'enable_text' in request.DATA and request.DATA['enable_text'] == True:
                request.DATA['text'] = self.object.text
            serializer = self.get_serializer(self.object, data=request.DATA,
                                             files=request.FILES, partial=partial)
    
            if not serializer.is_valid():
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
            try:
                self.pre_save(serializer.object)
            except ValidationError as err:
                # full_clean on model instance may be called in pre_save,
                # so we have to handle eventual errors.
                return Response(err.message_dict, status=status.HTTP_400_BAD_REQUEST)
    
            if self.object is None:
                self.object = serializer.save(force_insert=True)
                self.post_save(self.object, created=True)
                return Response(serializer.data, status=status.HTTP_201_CREATED)
    
            self.object = serializer.save(force_update=True)
            self.post_save(self.object, created=False)
            return Response(serializer.data, status=status.HTTP_200_OK)
    

    此代码取自 UpdateMixin 的 rest_framework 源代码。请特别注意if 'enable_text' in request.DATA and...request.DATA['text'] = self.object.text 行。这些是允许您执行所需功能的功能。基本上:

    • 如果您将带有 True 的 enable_text 与文本一起发送,文本将被修改。
    • 如果您将带有 False 的 enable_text 与文本一起发送,它将被忽略。

    请注意,此代码仅考虑当前请求中传递的 enable_text 的值。如果 enable_text 不在当前请求中,您可能还想检查self.object(即数据库实例本身)中的 enable_text 的值。

    【讨论】:

    • 感谢您的回答@djangozone。由于我使用基于类的视图 (ModelViewSet),您建议在哪里检查 checkfield 的值?在函数get_serializer_class 内部还是其他地方?
    • 再次感谢。对不起,我有点困惑。你能写一个小sn-p吗?
    • 我用更简单的解决方案更新了我的答案。希望现在很清楚。
    猜你喜欢
    • 2023-03-30
    • 2014-04-03
    • 2015-12-15
    • 2020-09-29
    • 2017-07-02
    • 2019-03-05
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    相关资源
    最近更新 更多