Django2:Web项目开发入门笔记(21)

2024年04月16日 django Python51

这一篇教程,我们一起来学习如何使用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/

展开阅读全文
相关内容