主题

众所周知,django.forms极其强大,不少的框架也借鉴了这个模式,如Scrapy。在表单验证时,django.forms是一绝,也是面向对象的经典表现。但要用它来渲染表单那就不好玩了,除非写框架。本文章主要缕一缕如何使用django.forms来做表单验证。

django项目基本信息

  • models.py
from django.db import models

class Article(models.Model):
title = models.CharField(max_length=50, verbose_name='标题')
content = models.TextField(verbose_name='内容')
create_date = models.DateTimeField(auto_now_add=True) def __str__(self):
return self.title
  • forms.py

    同目录下创建一个forms.py
from django.forms import ModelForm
from django import forms
from . models import Article
from django.core.exceptions import ValidationError class ArticleForm(ModelForm):
class Meta:
model = Article
exclude = ['id'] def clean(self):
cleaned_data = super().clean()
title = cleaned_data.get('title')
if 'My' not in title:
raise ValidationError('标题中必须包含My字样', code='title')
  • views.py

    在views中,创建一个增加Article的方法
def add(request):
if request.method == 'GET':
return render(request, 'add.html')
else:
form = ArticleForm(request.POST)
# 主要了解的是表单的验证
if form.is_valid():
form.save()
return HttpResponseRedirect('/show/')
else:
form.errors.as_data() # {'__all__': [ValidationError(['标题中必须包含My字样'])]}
form.errors.get_context() # {'errors': dict_items([('__all__', ['标题中必须包含My字样'])]), 'error_class': 'errorlist'}
d = form.errors.get_json_data() # {'__all__': [{'message': '标题中必须包含My字样', 'code': 'title'}]}
return HttpResponse(d.get('__all__'))

核心分析

如果是在admin中使用ModelForm的验证,那也是非常方便的,如果我们要在用户的前端响应中使用表单验证,且又不通过django.forms渲染的表单来传递验证结果,则需要看看源码:

ModelForm.errorserrorsErrorDict()的实例,ErrorDict源码:

class ErrorDict(dict, RenderableErrorMixin):
"""
A collection of errors that knows how to display itself in various formats. The dictionary keys are the field names, and the values are the errors.
""" template_name = "django/forms/errors/dict/default.html"
template_name_text = "django/forms/errors/dict/text.txt"
template_name_ul = "django/forms/errors/dict/ul.html" def __init__(self, *args, renderer=None, **kwargs):
super().__init__(*args, **kwargs)
self.renderer = renderer or get_default_renderer() def as_data(self):
return {f: e.as_data() for f, e in self.items()} def get_json_data(self, escape_html=False):
return {f: e.get_json_data(escape_html) for f, e in self.items()} def get_context(self):
return {
"errors": self.items(),
"error_class": "errorlist",
}

三个方法返回的都是字典,但数据结构不同,可以看情况而定。值得注意的是,在ArticleForm中,raise ValidationError时,如果code传入参数时,它将会在get_context()中显式体现出来。

总结

1、掌握这个原理,传统的全栈开发可以节省更多的时间。

2、多看源码

django中只使用ModleForm的表单验证,而不使用ModleForm来渲染的更多相关文章

  1. iview中Modal弹窗做form表单验证相关问题

    在modal中初始化状态,点击确定弹窗消失. 有的时候表单验证就不希望立刻消失 在iview官网中有自定义页头页脚 可以直接自定义使用 另一种验证写法 serform: { ctCatelogue: ...

  2. django form表单验证

    一. django form表单验证引入 有时时候我们需要使用get,post,put等方式在前台HTML页面提交一些数据到后台处理例 ; <!DOCTYPE html> <html ...

  3. 由表单验证说起,关于在C#中尝试链式编程的实践

    在web开发中必不可少的会遇到表单验证的问题,为避免数据在写入到数据库时出现异常,一般比较安全的做法是前端会先做一次验证,通过后把数据提交到后端再验证一次,因为仅仅靠前端验证是不安全的,有太多的htt ...

  4. Spring进行表单验证

    转自:https://www.tianmaying.com/tutorial/spring-form-validation 开发环境 IDE+Java环境(JDK 1.7或以上版本) Maven 3. ...

  5. nice-validator表单验证插件的简单使用

    前言 前端表单校验是过滤无效数据.假数据.有毒数据的第一步,是数据安全的第一道关卡,虽然我们不能100%相信客户端提交的数据(真正的校验还得在服务端进行),但设置前端表单校验也是至关重要的,自己写逻辑 ...

  6. nice-validator表单验证插件

    nice-validator表单验证插件的简单使用 前言 前端表单校验是过滤无效数据.假数据.有毒数据的第一步,是数据安全的第一道关卡,虽然我们不能100%相信客户端提交的数据(真正的校验还得在服务端 ...

  7. ElementUI表单验证攻略:解决表单项启用和禁用验证的切换,以及动态表单验证的综合性问题

    试想一种比较复杂的业务场景: 表格(el-table)的每一行数据的第一列是勾选框,最后一列是输入框.当某一行的勾选框勾上时,启用该行的输入框,并开启该行输入框的表单验证:取消该行的勾选框,则禁用该行 ...

  8. ASP.NET MVC Jquery Validate 表单验证的多种方式

    在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...

  9. [转]ASP.NET MVC Jquery Validate 表单验证的多种方式介绍

    在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...

  10. Jquery Validate 表单验证的多种方式

    ASP.NET MVC Jquery Validate 表单验证的多种方式 在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体 ...

随机推荐

  1. PTA 1126 Eulerian Path

    无向连通图,输出每个顶点的度并判断Eulerian.Semi-Eulerian和Non-Eulerian这3种情况,我们直接记录每个点所连接的点,这样直接得到它的度,然后利用深度优先和visit数组来 ...

  2. MQ系列6:消息的消费

    MQ系列1:消息中间件执行原理 MQ系列2:消息中间件的技术选型 MQ系列3:RocketMQ 架构分析 MQ系列4:NameServer 原理解析 MQ系列5:RocketMQ消息的发送模式 在之前 ...

  3. RAID5 IO处理之写请求代码详解

    我们知道RAID5一个条带上的数据是由N个数据块和1个校验块组成,其校验块由N个数据块通过异或运算得出,这样才能在任意一个成员磁盘失效时通过其他N个成员磁盘恢复出用户写入的数据.这也就要求RAID5条 ...

  4. iptables基本使用举例

    一.链的基本操作 1.清除所有的规则. 1)清除预设表filter中所有规则链中的规则. # iptables -F 2)清除预设表filter中使用者自定链中的规则. #iptables -X #i ...

  5. Codeforces Round #804 (Div. 2) C(组合 + mex)

    Codeforces Round #804 (Div. 2) C(组合 + mex) 本萌新的第一篇题解qwq 题目链接: 传送门QAQ 题意: 给定一个\(\left [0,n-1 \right ] ...

  6. python 运行错误收集

    目录 global全局声明错误 global全局声明错误 SyntaxError: name 'is_login' is used prior to global declaration 解决办法:g ...

  7. Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2020-02-06'; nested exception is java.lang.IllegalArgumentException]解决

    今天做springbook项目前端输入日期传到数据库保存报了一下错误 Whitelabel Error Page This application has no explicit mapping fo ...

  8. C++ 函数重载解析策略

    参考<C++ Primer Plus>(第6版)中文版,Stephen Prata 著,张海龙 袁国忠译,人民邮电出版社.C++ 使用重载解析策略来决定为函数调用使用哪一个函数定义.重载解 ...

  9. 生成随机数的几种方法、Math.random()随机数的生成、Random()的使用

    第一种方法使用:System.currentTimeMillis(); final long l = System.currentTimeMillis(); final int rs = (int) ...

  10. 使用thymeleaf将查询的数据显示在前台。通过使用循环的形式

    1.需要注意的点. 在 <tr th:each="book:${bookList}">中.book是自己命令的变量.${bookList}是将查询的数据放入这里,需要后 ...