Django forms使用容易, 又方便扩展, 因此Django admin和CBVs基本都基于forms使用. 事实上, 由于django forms的强大验证功能, 大多数Django API 框架都是用forms作为其验证的一部分.

虽然django forms的学习需要花费一点时间, 但如果将forms, models和views结合起来使用, 我们可以花费很少的经历来完成庞大的工作.

1. Django Forms的强大之处

有些django项目并不直接呈现HTML, 二是以API框架的形式存在, 但你可能没有想到, 在这些API形式的django项目中也用到了django forms. django forms不仅仅是用来呈现HTML的, 他们最强的地方应该是他们的验证能力. 下面我们就介绍几种和Django forms结合使用的模式:

2. 模式一: ModelForm和默认验证

最简单的使用模式便是ModelForm和model中定义的默认验证方式的组合:

# myapp/views.py
from django.views.generic import CreateView, UpdateView from braces.views import LoginRequiredMixin from .models import Article class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
fields = ('title', 'slug', 'review_num') class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article
fields = ('title', 'slug', 'review_num')

正如以上代码中看到的一样:

  • ArticleCreateView和ArticleUpdateView中设置model为Article
  • 两个view都基于Article model自动生成了ModelForm
  • 这些ModelForm的验证, 是基于Article model中定义的field转换而来的

3. 模式二, 在ModelForm中修改验证

在上面的例子中, 如果我们希望每篇article title的开头都是"new", 那么应该怎么做呢? 首先我们需要建立自定义的验证(validator):

# utils/validator.py
from django.core.exceptions import ValidationError def validate_begins(value):
if not value.startswith(u'new'):
raise ValidationError(u'Must start with new')

可见, 在django中的验证程序就是不符合条件便抛出ValidationError的function, 为了方便重复使用, 我们将它们放在django app utils的validators.py中.

接下来, 我们可以在model中加入这些validator, 但为了今后的方便修改和维护, 我们更倾向于加入到ModelForm中:

# myapp/forms.py
from django import forms from utils.validators import validate_begin
from .models import Article class ArticleForm(forms.ModelForm):
dev __init__(self, *args, **kwargs):
super(ArticleForm, self).__init__(8args, **kwargs)
self.fields["title"].validators.append(validate_begin) class Meta:
model = Article

Django的edit views(UpdateView和CreateView等)的默认行为是根据view中model属性, 自动创建ModelForm. 因此, 我们需要调用我们自己的Modelform来覆盖自动创建的:

# myapp/views.py
from django.views.generic import CreateView, UpdateView from braces.views import LoginRequiredMixin from .models import Article
from .forms import ArticleForm class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
fields = ('title', 'slug', 'review_num')
form_class = ArticleForm class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article
fields = ('title', 'slug', 'review_num')
form_class = ArticleForm

4. 模式三, 使用form的clean()和clean_<field>()方法

如果我们希望验证form中的多个field, 或者验证涉及到已经存在之后的数据, 那么我们就需要用到form的clean()和clean_<field>&()方法了. 以下代码检查密码长度是否大于7位, 并且password是否和password2相同:

# myapp/forms.py
from django import forms class MyUserForm(forms.Form):
username = forms.CharField()
password = forms.CharField()
password2 = forms.CharField() def clean_password(self):
password = self.cleaned_data['password']
if len(password) <= 7:
raise forms.ValidationError("password insecure") return password def clean():
cleaned_data = super(MyUserForm, self).clean()
password = cleaned_data.get('password', '')
password2 = cleaned_data.get('password2', '') if password != password2:
raise forms.ValidationError("passwords not match") return cleaned_data

其中需要注意的是, clean()和clean_<field>&()的最后必须返回验证完毕或修改后的值.

5. 模式四, 自定义ModelForm中的field

我们会经常遇到在form中需要修改默认的验证, 比如一个model中有许多非必填项, 但为了信息完整, 你希望这些field在填写时是必填的:

# myapp/models.py
from django.db import models class MyUser(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
address = models.TextField(blank=True)
phone = models.CharField(max_length=100, blank=True)

为了达到以上要求, 你可能会通过直接增加field改写ModelForm:

# 请不要这么做
# myapp/forms.py
from django import forms from .models import MyUser class MyUserForm(forms.ModelForm):
# 请不要这么做
address = forms.CharField(required=True)
# 请不要这么做
phone = forms.CharField(required=True) class Meta:
model = MyUser

请不要这么做, 因为这违反"不重复"的原则, 而且经过多次的拷贝粘贴, 代码会变得复杂难维护. 正确的方式应当是利用__init__():

# myapp/forms.py
from django import forms from .models import MyUser class MyUserForm(forms.ModelForm): def __init__(self, *args, **kwarg):
super(MyUserForm, self).__init__(*args, **kwargs)
self.fields['address'].required = True
self.fields['phone'].required = True class Meta:
model = MyUser

值得注意的是, Django forms也是Python类, 类可以继承和被继承, 也可以动态修改.

原文链接: http://www.weiguda.com/blog/12/

django form使用学习记录的更多相关文章

  1. 巨蟒django之CRM5 学习记录&&课程记录&&班级管理&&私户的数量上限

    1.公户变私户(事务+行级锁) 2.私户的数量上限 3.班级的管理 4.课程记录管理 5.学习记录的初始化 6.展示和编辑学习记录

  2. Django Form的学习

    django.forms 是Django处理form的库      本质上可以直接通过对HttpRequest达到同样的效果,但是django.from带来更便捷的处理方式.功能有几点 通过form类 ...

  3. django模型manager学习记录

    Managers 在语句Book.objects.all()中,objects是一个特殊的属性,需要通过它查询数据库. 在第5章,我们只是简要地说这是模块的manager .现在是时候深入了解mana ...

  4. django网站安全学习记录

    现在比较流行的网站攻击方式有sql注入,xss跨站脚本攻击,csrf跨站请求伪造,一句话木马等等 django非常强大,对这些攻击都做了防范 sql注入,通过在sql语句中插入非法的sql语句来实现爆 ...

  5. django view使用学习记录

    判断用户是否登录 request.user.is_authenticated()auth.authenticate(username=username, password=password)

  6. django models使用学习记录

    如何更新单个数据 example = User.objects.get(id=1) example.is_acitve=1 example.save() 如何更新多个数据 examples = Use ...

  7. [Django]模型学习记录篇--基础

    模型学习记录篇,仅仅自己学习时做的记录!!! 实现模型变更的三个步骤: 修改你的模型(在models.py文件中). 运行python manage.py makemigrations ,为这些修改创 ...

  8. Django学习笔记之Django Form表单详解

    知识预览 构建一个表单 在Django 中构建一个表单 Django Form 类详解 使用表单模板 回到顶部 构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的 ...

  9. Django学习笔记之Django Form表单

    Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...

随机推荐

  1. ubuntu12.04 登录黑屏

    新安装的ubuntu12.04LTS,登录之后黑屏,切换到ubuntu2D能够进入UI.解决方法记录于此. 转载: http://blog.csdn.net/albertsh/article/deta ...

  2. OProfile 性能分析工具

    OProfile 性能分析工具 官方网站:http://oprofile.sourceforge.net/news/ oprofile.ko模块本文主要介绍Oprofile工具,适用系统的CPU性能分 ...

  3. Android java取得当前日期增加一天或多天

    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); Calendar c = Calendar.getInstanc ...

  4. 团队冲刺the second day

    今天是我们的团队冲刺的第二天,由于我的电脑出现了一点问题,系统还原了,我有重新配置了一下环境变量和一些eclipse的问题,导致时间浪费了很多,但是我还是做了一些简单的任务,例如编写节日的页面的布局, ...

  5. vc2010 win32 控制台应用程序中文乱码

    vc2010 win32 控制台应用程序中文乱码 在 vc2010 上用 win32 控制台程序写些测试代码调用 windows api ,处理错误信息时,发现用 wprintf 输出的错误信息出现了 ...

  6. mysql的粗略学习

    输入root进入mysql 试着输入了两个语法都没动静,输入\h终于有反应了 语法错误 show databases; //显示数据库 为什么没有人告诉我还有个英文下的分隔符号... 查的资料不是没有 ...

  7. Map小记

    Corelocation地理定位Map Kit地图展示 在移动互联网的时代,移动app能解决用户的很多生活琐事,比如 导航:去任意陌生的地方 周边找餐馆找酒店,找银行,找电影院在上述应用中都用到了地图 ...

  8. python enumerate

    >>> a = [1, 2, 3] >>> for index, item in enumerate(a): print index, item 0 1 1 2 2 ...

  9. Linux bash运维操作日志审计(单服务器)

    目前公司有几台机器比较重要,需要把所有用户的操作记录下来,于是就是参照资料来完成 1. vim /etc/profile.d/oplogrc.sh logdir=/opt/oplog userdir= ...

  10. DTMF Stresstesting

    import threading,time,serial,sys from random import randrange   port_snd=14 port_recv=2 recnt=0 ser_ ...