这一篇教程,我们一起来学习如何使用ModelForm,通过模型创建表单。
假设,我们完成一个用户注册的功能,用户注册的内容包括:邮箱、密码、姓名、年龄、生日。
提示:不要纠结这样的注册信息对用户是否友好,我们只是通过它们进行练习,熟悉字段的使用以及一些对字段的处理方法。
首先,在“settings.py”中,先将当前应用添加到“INSTALLED_APPS”的列表中。
然后,我们开始编写代码。
一、在“models.py”中创建模型类“UserModel”。
示例代码:
from django.db import models class UserModel(models.Model): email = models.EmailField('邮箱') password = models.CharField('密码', max_length=256) name = models.CharField('姓名', max_length=20) age = models.IntegerField('年龄') birthday = models.DateField('生日')
创建完成后,使用“makemigrations”和“migrate”命令连接数据库创建数据表。
如果不知道上一句在说什么,请再次学习《Django2:Web项目开发入门笔记(7)》。
二、在“forms.py”中创建表单类“RegisterForm”。
示例代码:
from django import forms from FormTest import models # 导入模型模块 class RegisterForm(forms.ModelForm): # 继承ModelForm类 class Meta: model = models.UserModel fields = '__all__'
在上方代码中,表单类“RegisterForm”里面写了一个内嵌类“class Meta”,它能够让我们定义RegisterForm类的元数据。
在这个内嵌类中,model为表单类对应的模型类;fields为表单字段中所包含的模型类字段,“’__all__’”表示表单字段包含所有的模型类字段。
实际上这段代码相当于下方代码:
from django import forms class RegisterForm(forms.Form): email = forms.EmailField(label='邮箱') password = forms.CharField(label='密码', max_length=256) name = forms.CharField(label='姓名', max_length=20) age = forms.IntegerField(label='年龄') birthday = forms.DateField(label='生日')
那么,通过上方的代码,大家也能够看出模型字段和表单字段存在对应关系。
具体如下:
Model 字段 | Form 字段 |
---|---|
AutoField | 没有对应的字段 |
BigAutoField | 没有对应的字段 |
BigIntegerField | IntegerField(+-9223372036854775808之间) |
BooleanField | BooleanField |
CharField | CharField
max_length=8对应Model字段max_length=8 empty_value=None对应Model字段null=True |
DateField | DateField |
DateTimeField | DateTimeField |
DecimalField | DecimalField |
EmailField | EmailField |
FileField | FileField |
FilePathField | FilePathField |
FloatField | FloatField |
ForeignKey | ModelChoiceField |
ImageField | ImageField |
IntegerField | IntegerField |
IPAddressField | IPAddressField |
GenericIPAddressField | GenericIPAddressField |
ManyToManyField | ModelMultipleChoiceField |
NullBooleanField | NullBooleanField |
PositiveIntegerField | IntegerField |
PositiveSmallIntegerField | IntegerField |
SlugField | SlugField |
SmallIntegerField | IntegerField |
TextField | CharField(widget=forms.Textarea) |
TimeField | TimeField |
URLField | URLField |
三、创建模板
模板内容比较简单,无需过多解释。
示例代码:(register.html)
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>用户注册</title> </head> <body> <form action="/register/" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="注册"> </form> </body> </html>
四、添加URL分发配置
示例代码:
from django.urls import path from FormTest import views as form_views urlpatterns = [ path('register/', form_views.register), ]
五、创建视图函数,将表单与模板整合。
示例代码:
from django.shortcuts import render, HttpResponse from FormTest.forms import RegisterForm def register(request): if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid(): try: <strong>form.save()</strong> except: return HttpResponse('糟糕,注册失败了!!') return HttpResponse('恭喜您,注册成功!') form = RegisterForm() return render(request, 'register.html', {'form': form})
在上方代码中,大家注意标红的语句。
只需要这一句,我们就能够完成将表单数据写入数据库的操作。
这就是使用“ModelForm”的便捷之处。
不过,目前我们了解这些还不够。
例如,我们刚刚完成的注册界面,密码的输入能够看到内容。
但是,这些表单中字段的控件都是自动生成的,怎么能够让密码变为加密类型呢?
在forms中有PasswordInput类,能够产生密码类型的表单控件。
我们可以单独定义“password”字段,使用“PasswordInput”生成密码框控件。
在代码中,我们添加一段内容。
示例代码:
class RegisterForm(forms.ModelForm): # 继承ModelForm类 class Meta: model = models.UserModel fields = '__all__' <strong> widgets = {</strong> <strong> 'password': forms.PasswordInput()</strong> <strong> }</strong>
上方代码,在“widgets”字典中,添加一个键值对,键为Model字段的名称,值为表单控件对象。
使用这种方法,我们也可以定义表单中“label”控件的文字。
示例代码:
labels = { 'name': '芳名' }
还有,定义帮助信息。
示例代码:
help_texts = { 'birthday': ('日期格式:2018-2-28'), }
当然,错误信息也可以照此操作。
示例代码:
error_messages = { 'name': { 'max_length': ("你那个太长了啦!."), }, }
另外,我们还可以指定字段使用其他类型(可以是自定义字段类型)。
因为没有自定义字段,下方代码使用forms中自带的字段进行演示。
示例代码:
field_classes = { 'age': forms.CharField }
除了上述这些,在“class Meta”中还有更多的功能。
大家肯定想到了,有时我们并不想把Model中的所有字段都生成表单控件。
这只需要把需要的字段赋值给“fields”。
示例代码:
fields = ['email', 'password', 'age']
或者,我们只有少数的字段想要排除在外。
也可以使用下方的代码。
示例代码:
exclude = ['birthday']
以上是关于“class Meta”的使用。
接下来,我们再一起了解一下“save()”方法的相关内容。
在前面的示例中,我们已经看到通过“save()”方法,可以将表单数据直接存入数据库。
不过,我们在使用过程中还会有其他的需求。
1、表单字段值修改后,存入数据库。
例如,我们把密码加密后存入数据库。
示例代码:
from django.shortcuts import render, HttpResponse from FormTest.forms import RegisterForm <strong>from hashlib import md5</strong> def register(request): if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid(): <strong> email = form.cleaned_data['email']</strong> <strong> password = form.cleaned_data['password']</strong> try: <strong> new_form = form.save(commit=False)</strong> <strong> m = md5()</strong> <strong> m.update((email + password).encode('utf-8'))</strong> <strong> new_form.password = m.hexdigest()</strong> <strong> new_form.save()</strong> <strong> form.save_m2m()</strong> except: # raise return HttpResponse('糟糕,注册失败了!!') return HttpResponse('恭喜您,注册成功!') form = RegisterForm() return render(request, 'register.html', {'form': form})
上方代码中,红色部分为新增代码。
2、一些字段无需用户填写,由系统自动给定。
例如,注册时无需用户填写生日,系统自动给定默认值,留作以后用户自行修改。
我们可以先在表单类中排除“birthday”字段。
示例代码:
class RegisterForm(forms.ModelForm): class Meta: model = models.UserModel <strong>exclude = ['birthday']</strong>
然后,在视图函数中,创建一个Model对象,设置“birthday”字段的默认值,并添加到表单对象中。
示例代码:
...省略部分代码... <strong>from FormTest.models import UserModel</strong> def register(request): if request.method == 'POST': <strong> user =UserModel(birthday='1990-1-1')</strong> <strong> form = RegisterForm(request.POST,instance=user)</strong> if form.is_valid(): ...省略部分代码...
以上就是关于将表单数据存入数据库的一些操作,另外还有“save_m2m()”方法,用于多对多(many to many)数据的保存,我们还没有接触过多对多的数据库操作,在此不做演示。
最后一部分内容,关于使用ModelForm 的工厂函数(factory function)。
之前,我们都是通过表单类完成一个表单的创建。
其实,我们还可以采用ModelForm 的工厂函数方式创建表单。
例如下方这个表单。
示例代码:
from django import forms from FormTest import models class RegisterForm(forms.ModelForm): class Meta: model = models.UserModel fields = ['email', 'password', 'age']
使用“ModelForm factory function”实现,如下。
示例代码:
from django import forms from FormTest import models RegisterForm= forms.modelform_factory(models.UserModel,fields=('email', 'password', 'age'))
那么,如果需要对表单控件进行修改,或者添加帮助提示如何处理呢?
示例代码:
from django import forms from FormTest import models RegisterForm= forms.modelform_factory(models.UserModel, fields=('email', 'password', 'age'), widgets={'password':forms.PasswordInput}, help_texts={'email':'请输入有效的邮箱地址!'})
结合本篇教程前面的内容,大家可以很快掌握ModelForm工厂函数的使用方法。
本文链接:http://so.lmcjl.com/news/2260/