前言:

  为什么要用form去验证呢?

  我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理,那样会不会对我们系统产生影响?答案是肯定的,FORM的作用就是起到一定的数据保护作用加一层校验将不合法数据丢弃

1.针对上一章 django form表单验证 补充

form表单补充,select框

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import re
  4. from django import forms
  5. from django.core.exceptions import ValidationError
  6.  
  7. def phone_validate(value):
  8. phone_re = re.compile(r'^(13[0-9]|15[012356789]|17[0678]|18[0-9]|14[57])[0-9]{8}$')
  9. if not phone_re.match(value):
  10. raise ValidationError('手机号码格式错误')
  11.  
  12. class TestForm(forms.Form):
  13. user_type_choice = (
  14. (0, u'普通用户'),
  15. (1, u'管理员'),
  16. )
  17.  
  18. user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
  19. attrs={'class': "form-control"}))

 注:

  widget 生成前端展示 .SELECT选择下拉框,attrs属性class前端显示类

二. 通过model form来自定义表单

1. 字段类型

生成的表单类中将具有和指定的模型字段对应的表单字段,顺序为fields 属性中指定的顺序。

Form field
AutoField Not represented in the form
BigIntegerField IntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807.
BooleanField BooleanField
CharField CharField with max_length set to the model field’s max_length
CommaSeparatedIntegerField CharField
DateField DateField
DateTimeField DateTimeField
DecimalField DecimalField
EmailField EmailField
FileField FileField
FilePathField FilePathField
FloatField FloatField
ForeignKey ModelChoiceField (see below)
ImageField ImageField
IntegerField IntegerField
IPAddressField IPAddressField
GenericIPAddressField GenericIPAddressField
ManyToManyField ModelMultipleChoiceField (see below)
NullBooleanField NullBooleanField
PositiveIntegerField IntegerField
PositiveSmallIntegerField IntegerField
SlugField SlugField
SmallIntegerField IntegerField
TextField CharField with widget=forms.Textarea
TimeField TimeField
URLField URLField

完整示例:

1. 数据模型

创建:

  1. from django.db import models
  2.  
  3. # Create your models here.
  4.  
  5. class Publisher(models.Model):
  6. name = models.CharField(max_length=30, unique=True)
  7. address = models.CharField(max_length=50)
  8. city = models.CharField(max_length=60)
  9. state_province = models.CharField(max_length=60)
  10. country = models.CharField(max_length=60)
  11. website = models.URLField()
  12.  
  13. def __str__(self):
  14. return self.name
  15.  
  16. class Author(models.Model):
  17. first_name = models.CharField(max_length=32)
  18. last_name = models.CharField(max_length=32)
  19. email = models.EmailField()
  20.  
  21. def __str__(self):
  22. name = self.first_name + self.last_name
  23. return name
  24.  
  25. class Book(models.Model):
  26. name = models.CharField(max_length=128)
  27. authors = models.ManyToManyField(Author)
  28. publisher = models.ForeignKey(Publisher)
  29. publish_date = models.DateField()
  30.  
  31. def __str__(self):
  32. return self.authors

model.py

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME': os.environ.get("MYSQL_NAME", 'modelform'),
  5. 'USER': os.environ.get("MYSQL_USER", 'root'),
  6. 'PASSWORD': os.environ.get("MYSQL_PASSWD", 'password'),
  7. 'HOST': os.environ.get("MYSQL_HOST", '192.168.1.102'),
  8. 'PORT': os.environ.get("MYSQL_PORT", 3306),
  9. }
  10. }

settings DATABASES配制

生成:

  python manage.py makemigrations

  python manage.py migrate

只是举例详见参考

https://docs.djangoproject.com/en/1.11/topics/db/models/

http://www.cnblogs.com/jl-bai/p/5798860.html

注:

报错:

  django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'

原因:无mysql客户端

解决方案:

  在project 的root_dir 下__init__文件中写入

  1. import pymysql
  2. pymysql.install_as_MySQLdb()

(一)数据前端展示 

2. 后台VIEWS

  1. from django.views.generic.base import TemplateView
  2. from app01.forms import BookModelForm
  3.  
  4. class Index(TemplateView):
  5. template_name = "index.html"
  6.  
  7. def get(self, request, *args, **kwargs):
  8. form = BookModelForm()
  9. return self.render_to_response(context={"form": form})

3. ModelForm

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from django import forms
  4. from app01.models import Book
  5.  
  6. class BookModelForm(forms.ModelForm):
  7. class Meta:
  8. model = Book
  9. fields = ['name', 'authors', 'publish_date']
  10. widgets = {
  11. 'name': forms.TextInput(attrs={'class': "form-control"}),
  12. 'authors': forms.Select(attrs={'class': "form-control"}),
  13. 'publish_date': forms.DateInput(attrs={'class': "form-control",
  14. 'placeholder': "YYYY-MM-DD"})
  15. }

4. 前端展示

  1. {% load staticfiles %}
  2. {% load i18n admin_static %}
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>django model form</title>
  8. <link href="{% static 'css/bootstrap.css' %}" rel="stylesheet"/>
  9. </head>
  10. <body>
  11. <div style="width: 980px;margin: 0 auto">
  12. <div class="col-lg-6">
  13. <form action="{% url 'index' %}" method="POST">{% csrf_token %}
  14. {{ form }}
  15. <input class="btn btn-primary m-r-5 m-b-5" type="submit" value="提 交">
  16. </form>
  17. </div>
  18. </div>
  19.  
  20. </body>
  21. </html>

访问:

(二) 模型表单的验证

1. 验证模型

与普通的表单验证类型类似,模型表单的验证在调用is_valid() 或访问errors 属性时隐式调用,或者通过full_clean() 显式调用,尽管在实际应用中你将很少使用后一种方法。

模型的验证(Model.full_clean())在表单验证这一步的内部触发,紧跟在表单的clean() 方法调用之后。

警告

  Clean 过程会以各种方式修改传递给模型表单构造函数的模型实例。例如,模型的日期字段将转换成日期对象。验证失败可能导致模型实例处于不一致的状态,所以不建议重新使用它。

1.1 重写clean() 方法

可以重写模型表单的clean() 来提供额外的验证,方法和普通的表单一样。

模型表单实例包含一个instance 属性,表示与它绑定的模型实例。

警告

ModelForm.clean() 方法设置一个标识符, 使得模型验证 这一步验证标记为unique、 unique_together 或unique_for_date|month|year 的模型字段的唯一性。

如果你需要覆盖clean() 方法并维持这个验证行为,你必须调用父类的clean() 方法。

django form表单验证 中定义clean方法相同

模型error_messages 的注意事项

表单字段级别或表单级别的错误信息永远比模型字段级别的错误信息优先。

模型字段的错误信息只用于模型验证步骤引发ValidationError 的时候,且不会有对应的表单级别的错误信息。

2. save()方法

每个ModelForm还具有一个save() 方法。这个方法根据表单绑定的数据创建并保存数据库对象。模型表单的子类可以用关键字参数instance 接收一个已经存在的模型实例;如果提供,save() 将更新这个实例。如果没有提供,save() 将创建模型的一个新实例:

  1. class Index(TemplateView):
  2. template_name = "index.html"
  3.  
  4. def get(self, request, *args, **kwargs):
  5. form = BookModelForm()
  6. return self.render_to_response(context={"form": form})
  7.  
  8. def post(self,request):
  9. form = BookModelForm()
  10. if form.is_valid():
  11. form.save()
  12. return redirect("home")
  13. return self.render_to_response(context={"form": form})

save()

如果表单没有验证,save() 调用将通过检查form.errors 来进行验证。如果表单中的数据不合法,将引发ValueError —— 例如,如果form.errors 为True

3. 先择用到的字段

  

  1. class BookModelForm(forms.ModelForm):
  2. class Meta:
  3. model = Book
  4. fields = ['name', 'authors', 'publish_date']
  5. widgets = {
  6. 'name': forms.TextInput(attrs={'class': "form-control"}),
  7. 'authors': forms.Select(attrs={'class': "form-control"}),
  8. 'publish_date': forms.DateInput(attrs={'class': "form-control",
  9. 'placeholder': "YYYY-MM-DD"})
  10. }

在ModelForm中我们通常使用fields 属性显式设置所有将要在表单中编辑的字段,如果不这样做,当表单不小心允许用户设置某些特定的字段,特别是有的字段添加到模型中的时候,将很容易导致安全问题。

另外一种方式是自动包含所有的字段,或者排除某些字段。这种基本方式的安全性要差很多,而且已经导致大型的网站受到严重的利用。

3.1 设置fields 属性为特殊的值'__all__' 以表示需要使用模型的所有字段。例如:
  1. class BookModelForm(forms.ModelForm):
  2. class Meta:
  3. model = Book
  4. fields = '__all__'
3.2 设置ModelForm 内联的Meta 类的exclude 属性为一个要从表单中排除的字段的列表
  1. class BookModelForm(forms.ModelForm):
  2. class Meta:
  3. model = Book
  4. exclude = ()
  1. exclude = () fields = '__all__' 达到效果相同选取所有字段
    如果 exclude=['name'],那么排除“name"字段其他字段都会显示
3.3 多个外键对同一个模型
  1. 如果一个模型在同一个模型中包含多个外键,则需要使用fk_name手动解决歧义。例如,考虑以下模型:
  1. class Friendship(models.Model):
  2. from_friend = models.ForeignKey(Friend, related_name='from_friends')
  3. to_friend = models.ForeignKey(Friend, related_name='friends')
  4. length_in_months = models.IntegerField()

要解决此问题,您可以使用fk_nameinlineformset_factory()

  1. FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name='from_friend',
  2. ... fields=('to_friend', 'length_in_months'))

具体参考:

https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/

django Modelform的更多相关文章

  1. python 全栈开发,Day110(django ModelForm,客户管理之 编辑权限(一))

    昨日内容回顾 1. 简述权限管理的实现原理. 粒度控制到按钮级别的权限控制 - 用户登陆成功之后,将权限和菜单信息放入session - 每次请求时,在中间件中做权限校验 - inclusion_ta ...

  2. 【python】-- Django ModelForm

    Django ModelForm Django的ModelForm的验证方式相比较form + Model的验证方式有下列区别: ModelForm没有form + Model的低耦合性 ModelF ...

  3. django modelform中的self.instance

    在stackoverflow上看到一个问题,正好是我疑惑很久的相关问题. [原问题地址]https://stackoverflow.com/questions/18265023/self-instan ...

  4. 关于Django ModelForm渲染时间格式问题

    关于Django ModelForm渲染时间格式问题 直接定义DateTimeInput或者DateTimeFile是不行的,渲染在html页面中的仍然是Input text类型 解决办法:自定义小部 ...

  5. Django ModelForm and Form

    django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm 关于django的表单系统,主要分两种 基于django.forms.Form 基于dj ...

  6. Django ModelForm修改默认的控件属性

    Django 中利用ModelForm 可以快速地利用数据库对应的Model 子类来自动创建对应表单. 例如: from django.db import models from django.for ...

  7. 33.Django ModelForm

    ModelForm 1.ModeForm简单验证 from django.db import models # Create your models here. class UserInfo(mode ...

  8. 10.Django ModelForm

    ModelForm 1.ModeForm简单验证 from django.db import models # Create your models here. class UserInfo(mode ...

  9. Django ModelForm 校验数据格式

    发现ModelForm很好用,用来做form表单验证效果很好.但是也要注意几点. forms的用法: 使用默认方式:继承forms.Form类,类里面的字段名称一定要和前端HTML里面的form表单里 ...

随机推荐

  1. JVM-2.Class文件结构

    1.Class文件 (1)无关性:除了平台无关性,JVM还支持语言无关性:目前Clojure.Groovy.JRuby.Jyphon.Scala等语言可以在JVM上运行.实现语言无关性的原理仍然是字节 ...

  2. JavaSE教程-04Java中循环语句for,while,do···while-练习2

    1.编写一个剪子石头布对战小程序 该法是穷举法:将所有情况列出来 import java.util.*; public class Game{ public static void main(Stri ...

  3. [原创]使用logcat快速抓取android崩溃日志

    在android APP测试过程中会发生不少的crash,目前抓取日志的主流方法是通过eclipse或者eclipse的ddms组件进行捕抓,这两种方法有个缺点是启动时非常耗时.本文通过adb程序与b ...

  4. springboot问题:解决异常Unable to start embedded container;

    使用eclipse创建springboot练习时,当主函数与控制器同时写在同一个类时,启动项目正常运行,而当把主函数单独放在一个类中时,无论是与控制器同包还是控制器所在的包是其子包,都报: org.s ...

  5. 每篇半小时1天入门MongoDB——3.MongoDB可视化及shell详解

    本篇主要介绍MongoDB可视化操作以及shell使用及命令,备份恢复.数据导入导出. MongoVUE安装和简单使用 使用mongo.exe 管理数据库虽然可行,功能也挺强大,但每次都要敲命令,即繁 ...

  6. .Net Core 图片文件上传下载

    当下.Net Core项目可是如雨后春笋一般发展起来,作为.Net大军中的一员,我热忱地拥抱了.Net Core并且积极使用其进行业务的开发,我们先介绍下.Net Core项目下实现文件上传下载接口. ...

  7. SICP-1.6-高阶函数

    高阶函数 将函数作为参数 例如 def sum_naturals(n): total, k = 0, 1 while k <= n: total, k = total + k, k + 1 re ...

  8. PHP 判断是否包含在某个字符串中

    1.用strpos函数,查找字符首次出现的位置,如果不存在则会返回false$str= 'abc';$needle= 'e';$pos = strpos($str, $needle);2.用strst ...

  9. test_markdown

    add modifications 非科学计数法显示数字 citation[^ref1] format bank% do not use scientific expression format lo ...

  10. 15套java架构师、集群、高可用、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战视频教程

    * { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩展. ...