这一篇教程,我们一起来学习如何使用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工厂函数的使用方法。
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试
 
                     
                


