资讯专栏INFORMATION COLUMN

Django的数据验证(validating objects)

张汉庆 / 766人阅读

摘要:在中,对数据进行校验有两种方式一种是通过中校验,一种是通过校验。所有内容都是基于的官网文档整理而来数据校验的触发中的校验是通过调用方法来执行的。注意值得注意的是上面多次提到,在执行方法的时候,是不会进行数据校验的。

在Django中,对数据进行校验有两种方式:一种是通过Form中校验,一种是通过Model校验。在次,我对Model中的校验方法做下记录。

所有内容都是基于Django1.10的官网文档整理而来

validating objects 数据校验的触发:

Model中的校验是通过调用Model.full_clean()方法来执行的。包括在Form中也会对objects进行校验,也是通过调用Model.full_clean()的方式来进行的。但是,通常的情况下我们并不需要自己调用Model.full_clean()方法。

什么时候需要调用full_clean()

当你使用ModelForm的时候,Model.full_clean()将会在你调用is_valid()方法的时候对ModelForm中所有的field进行校验。只有当你想要自己特别的处理校验的报错信息,或者是想要校验在ModelForm中没有包含的field时才需要来自己调用full_clean()这个方法。

Model.full_clean说明

Model.full_clean(exclude=None, validate_unique=True)
Model.full_clean()内部其实是会通过3个方法来进行不同层次的校验,对于这3个方法在后面会讲到。

参数:

可选参数exclude可以用来指定不需要执行校验的field。ModelForm也利用这个参数来将field排除。
参数validate_unique用来指定是否需要执行Model.validate_unique()

如何检查校验结果:

full_clean将会按序执行3个方法,这3个方法如果校验失败的话,会将相关信息写到异常的message_dict属性中,并且抛出ValidationError异常。

save()执行的时候是不会自动调用full_clean()来进行校验的。

手动校验model的合法性:
from django.core.exceptions import ValidationError
try:
    article.full_clean()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.
    pass
3个校验方法:

校验model fields - Model.clean_fields()

校验整个model - Model.clean()

校验field的唯一性 - Model.validate_unique()

这几个步骤将会在调用model的full_clean()方法时执行,流程如下:

st=>start: Model.full_clean
e=>end: return
io=>inputoutput: rais ValidationError
sub1=>subroutine: Model.clean_fields
cond1=>condition: valid
sub2=>subroutine: Model.clean
cond2=>condition: valid
sub3=>subroutine: Model.validate_unique
cond3=>condition: valid

st->sub1->cond1(yes)->sub2->cond2(yes)->sub3->cond3(yes)->e
st->sub1->cond1(no)->io
st->sub1->cond1(yes)->sub2->cond2(no)->io
st->sub1->cond1(yes)->sub2->cond2(yes)->sub3->cond3(no)->io
Model.clean_fields

Model.clean_fields(exclude=None)
这个方法将会校验排除exclude中指定的,model中的所有field。当它校验失败的时候,会抛出ValidationError异常。

Model.clean

如果你想要自定义model的校验,或者想要修改model的属性的话,就override这个方法。例如,你可以使用它来为field自动提供一个值:

import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _

class Article(models.Model):
    ...
    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()

当调用model的save()方法的时候,是不会调用Model.clean来进行校验的

校验中的错误处理

在上面的例子中,我们使用了ValidationError来在Model.clean中抛出错误,这个错误信息将会存储在以NON_FIELD_ERRORS为key的字典中。这个key是用来存储对于整个model中的错误信息的。

如何获取校验的错误信息:

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

如何指定对于某个特定的field的校验错误信息:

class Article(models.Model):
    ...
    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({"pub_date": _("Draft entries may not have a publication date.")})
        ...

如何指定多个field的校验错误信息:

raise ValidationError({
    "title": ValidationError(_("Missing title."), code="required"),
    "pub_date": ValidationError(_("Invalid date."), code="invalid"),
})
Model.validate_unique说明

Model.validate_unique(exclude=None)
最后,full_clean()将会检查model中的unique的限制。它在校验失败的时候会抛出ValidationError异常。

注意

值得注意的是:上面多次提到,在执行save()方法的时候,是不会进行数据校验的。校验应该在save()执行之前完成,你可以先在form进行校验,也可以在model中进行校验。但是,你必须确保通过这两个校验之后的数据是绝对没有问题的“干净”数据,然后再调用save()方法将数据存储入库。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38170.html

相关文章

  • 10-django——RESTful API 之序列化

    摘要:之序列化前后端分离就是前台的开发和后台的开发分离,这个技术方案的实现需要借助,简单来说就是开发人员提供编程的接口被其他人调用,调用之后会返回数据供其使用安装什么是序列化把模型对象转换为格式然后响应出去,便于客户端进行数据解析创建序列化类在应 Django RESTful API之序列化 前后端分离:就是前台的开发和后台的开发分离,这个技术方案的实现需要借助API,简单来说就是开发人员提...

    Bowman_han 评论0 收藏0
  • Python学习之路18-用户账户

    摘要:通过的定制字段的输入小部件,将文本框的宽度设置为列,而不是默认的列。为此将创建一个新的应用程序,其中包含处理用户账户相关的所有功能。该函数将会为通过了身份验证的用户对象创建会话。 《Python编程:从入门到实践》笔记。本篇记录如何创建用户注册系统,如何实现用户输入自己的数据。 1. 前言 在本篇中,我们将: 创建一些表单,让用户能够添加主题和条目,以及编辑既有的条目; 实现一个身份...

    bovenson 评论0 收藏0
  • Django 学习小组:博客开发实战第五周教程 —— 实现评论功能

    摘要:本教程内容已过时,更新版教程请访问博客开发入门教程。我们的评论表单放在中,评论成功后返回到原始提交页面。学习小组简介学习小组是一个促进新手互相学习互相帮助的组织。 本教程内容已过时,更新版教程请访问: django 博客开发入门教程。 通过前四周的时间我们开发了一个简单的个人 Blog,前几期教程地址: 第一周:Django 学习小组:博客开发实战第一周教程 —— 编写博客的 Mode...

    CoderStudy 评论0 收藏0
  • Django 学习小组:博客开发实战第五周教程 —— 实现评论功能

    摘要:本教程内容已过时,更新版教程请访问博客开发入门教程。我们的评论表单放在中,评论成功后返回到原始提交页面。学习小组简介学习小组是一个促进新手互相学习互相帮助的组织。 本教程内容已过时,更新版教程请访问: django 博客开发入门教程。 通过前四周的时间我们开发了一个简单的个人 Blog,前几期教程地址: 第一周:Django 学习小组:博客开发实战第一周教程 —— 编写博客的 Mode...

    kumfo 评论0 收藏0
  • Django REST FrameWork中文教程3:基于类视图

    摘要:看起来不错再次,它现在仍然非常类似于基于功能的视图。我们还需要重构一下我们使用基于类的视图。中文文档目录中文教程序列化中文教程请求和响应中文教程基于类的视图中文教程验证和权限中文教程关系和超链接中文教程中文教程模式和客户端库 我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图。我们将看到这是一个强大的模式,允许我们重用常用功能,并帮助我们保持代码DRY。 使用基于类的...

    UnixAgain 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<