【问题标题】:Django: How to check if data is correct before saving it to a database on a post request?Django:如何在发布请求将数据保存到数据库之前检查数据是否正确?
【发布时间】:2019-08-23 19:08:05
【问题描述】:

我希望能够通过将数据发送到我的函数来解析我的 django rest api 项目中的发布请求中的数据向发出请求的客户端发送自定义错误请求消息。

我被告知我可以覆盖 create 方法来执行此操作,但我不知道该怎么做。

到目前为止,我的代码如下所示:

class Messages(models.Model):
    phone_number = models.CharField(max_length=256, default='')
    message_body = models.CharField(max_length=256, default='')
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.phone_number + ' ' + self.message_body + ' ' + self.created

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        # I assume this is where I would do the check before saving it but not sure how? example would be like:
        # if numberValid(self.phone_number):
        #    then save to the database
        # else:
        #    then send back a bad request?
        super(Messages, self).save(force_update=force_update)
        send_sms(self.phone_number, self.message_body)

    def delete(self, using=None, keep_parents=False):
        super(Messages, self).delete(using=using, keep_parents=keep_parents)

所以基本上只是想知道如何解决这个问题。甚至有用的链接将不胜感激。我确实看过stackoverflow但没有成功,也许我在搜索时不知道如何正确表达问题。

【问题讨论】:

    标签: python django api validation django-rest-framework


    【解决方案1】:

    您可以使用 DRF 串行器的validation。例如,创建一个序列化程序,并添加一个名为validate_<field_name> 的验证方法。然后在那里添加验证码:

    import re
    
    class MessagesSerializer(serializers.ModelSerializer):
        class Meta:
            model = Messages
            fields = "__all__"
    
        def validate_phone_number(self, value):
            rule = re.compile(r'(^[+0-9]{1,3})*([0-9]{10,11}$)')
            if not rule.search(value):
                raise serializers.ValidationError("Invalid Phone Number")
            return value
    

    并在视图中使用它:

    class SomeView(APIView):
        def post(self, request, *args, **kwargs):
           serializer = MessagesSerializer(
                data=request.data
            )
           if serializer.is_valid():  # will call the validate function
              serializer.save()
              return Response({'success': True})
           else:
              return Response(
                   serializer.errors,
                   status=status.HTTP_400_BAD_REQUEST
              )
    

    【讨论】:

    • 这正是我所需要的。我是根据其他人给我的链接得出这个结论的。但唯一的区别是我不需要改变任何东西,目前它仍然有两行长。稍后会发现这是否会遇到错误我敢肯定,我在学习时将永远在我的代码中出错。
    【解决方案2】:

    Model.save() 是一个选项,尽管它更常见​​于 validate input data,例如在 DRF 序列化程序中发布的电话号码。

    在哪里执行检查是您可以根据关注点分离原则做出的决定。

    【讨论】:

    • 我决定在序列化器中进行检查。这有助于我让事情变得更加独立,更容易理解发生了什么。谢谢你的链接。它帮助我获得了更多的理解。
    【解决方案3】:

    查看官方文档了解如何执行此操作:https://docs.djangoproject.com/en/2.2/ref/models/instances/#django.db.models.Model.clean

    此方法应用于提供自定义模型验证,并在需要时修改模型上的属性。例如,您可以使用它来自动为字段提供值,或者进行需要访问多个字段的验证:

    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError(_('Draft entries may not have a publication date.'))
        # Set the pub_date for published items if it hasn't been set already.
        if self.status == 'published' and self.pub_date is None:
            self.pub_date = datetime.date.today()
    

    实现一个clean 方法,如果检测到数据有问题,该方法将引发ValidationError。然后,您可以通过调用 model_obj.full_clean() 在视图中捕捉到这一点:

    from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
    try:
        article.full_clean()
    except ValidationError as e:
        non_field_errors = e.message_dict[NON_FIELD_ERRORS]
    

    【讨论】:

    • 谢谢,我看过这个,它让我非常需要了解我不知道自己错过了什么!
    【解决方案4】:

    您希望在保存之前验证字段。

    有很多技术可以做到这一点。

    对于您的情况,我会建议第二种选择。覆盖文档中的方法 clean_fields。然后在保存之前调用该方法。

    【讨论】:

    • 我决定采用第一种方法只是因为我似乎比第二种更清楚地掌握了这个概念。但谢谢你的链接。帮了大忙!
    猜你喜欢
    • 2023-03-06
    • 2014-03-13
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    相关资源
    最近更新 更多