django Modelform 使用

前言:css

  为何要用form去验证呢?html

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

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

form表单补充,select框python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
from django import forms
from  django.core.exceptions import ValidationError


def phone_validate(value):
    phone_re = re.compile(r'^(13[0-9]|15[012356789]|17[0678]|18[0-9]|14[57])[0-9]{8}$')
    if not phone_re.match(value):
        raise ValidationError('手机号码格式错误')

class TestForm(forms.Form):
    user_type_choice = (
        (0, u'普通用户'),
        (1, u'管理员'),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                               attrs={'class': "form-control"}))

 注:mysql

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

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

1. 字段类型

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

 

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. 数据模型django

建立:bootstrap

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

import pymysql
pymysql.install_as_MySQLdb()

(一)数据前端展现 

2. 后台VIEWS

from django.views.generic.base import TemplateView
from app01.forms import BookModelForm


class Index(TemplateView):
    template_name = "index.html"

    def get(self, request, *args, **kwargs):
        form = BookModelForm()
        return self.render_to_response(context={"form": form})

3. ModelForm

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django import forms
from app01.models import Book


class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['name', 'authors', 'publish_date']
        widgets = {
            'name': forms.TextInput(attrs={'class': "form-control"}),
            'authors': forms.Select(attrs={'class': "form-control"}),
            'publish_date': forms.DateInput(attrs={'class': "form-control",
                                                   'placeholder': "YYYY-MM-DD"})
        }

 

4. 前端展现

{% load staticfiles %}
{% load i18n admin_static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>django model form</title>
     <link href="{% static 'css/bootstrap.css' %}" rel="stylesheet"/>
</head>
<body>
<div style="width: 980px;margin: 0 auto">
    <div class="col-lg-6">
        <form action="{% url 'index' %}" method="POST">{% csrf_token %}
            {{ form }}
            <input class="btn btn-primary m-r-5 m-b-5" type="submit" value="提 交">
        </form>
    </div>
</div>

</body>
</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. 先择用到的字段

  

class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['name', 'authors', 'publish_date']
        widgets = {
            'name': forms.TextInput(attrs={'class': "form-control"}),
            'authors': forms.Select(attrs={'class': "form-control"}),
            'publish_date': forms.DateInput(attrs={'class': "form-control",
                                                   'placeholder': "YYYY-MM-DD"})
        }

在ModelForm中咱们一般使用fields 属性显式设置全部将要在表单中编辑的字段,若是不这样作,当表单不当心容许用户设置某些特定的字段,特别是有的字段添加到模型中的时候,将很容易致使安全问题。

另一种方式是自动包含全部的字段,或者排除某些字段。这种基本方式的安全性要差不少,并且已经致使大型的网站受到严重的利用。

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

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

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

具体参考:

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

相关文章
相关标签/搜索