Django表单模型

在应用新建一个forms.py文件:

from django.contrib.auth.forms import UserCreationForm
from .models import User
from django import forms
from django.utils.translation import gettext as _

#自定义的用户注册表单
class CustomUserCreationForm(UserCreationForm):  #继承自标准注册表单
    #这里入如果添加了就会展示,要编辑顺序在下面的fields中
    email_code = forms.CharField(max_length=6,label=_('邮件验证码'),help_text=_('输入Email收到的验证码'),required=True)  # 用于输入邮件确认验证码的字段,required为必填

    class Meta(UserCreationForm.Meta):
        model = User  #基于User模型,要查看user表有什么字段
        fields = ('username', 'email', 'email_code', 'password1', 'password2', 'beiyaoqing')  # 这是输入要展示的内容和顺序

视图函数:

from django.shortcuts import render, redirect
from .forms import CustomUserCreationForm  #导入自定义的注册表单

def register_view(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            # 注册成功后跳转到其他页面
            return redirect('login')
    else:
        form = CustomUserCreationForm()
    return render(request, 'register.html', {'form': form})

在视图中为表单传递额外的变量

#视图这边在指定表单的时候
form = ResetpasswordForm2(request.POST,initial={'email': email})


表单那边读取这个变量
class ResetpasswordForm2(forms.ModelForm):
    # 表单的字段定义等

    def clean(self):
        email = self.initial['email']  # 获取传递的email变量
        # 其他验证逻辑
        return self.cleaned_data

模板简单引用:

<form method="post">
    <!-- 注意csrf_token是函数不是变量引用 -->
        {% csrf_token %}
        {{ form.as_p }}<!-- 显示表全部 -->
        <button type="submit">{% trans "注册" %}</button>
    </form>

自定义模型表单

在forms.py新建一个表单

#验证邮箱表单
from .models import User
from django import forms
from django.utils.translation import gettext as _
from django.utils import timezone

class VEmailForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ["vcode"]  #自定义了一个核验验证码表单

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['vcode'].widget.attrs['placeholder'] = _('输入您收到的验证码')
        self.fields['vcode'].widget.attrs['class'] = 'input mb-3'

    def clean_vcode(self):
        #判断用户是否存在验证码
        if not self.instance.vcode:
            raise forms.ValidationError(_('没有验证码,您要重新获取验证码'))
        #判断用户上次请求时间
        print(f'验证码时间{self.instance.vcode_date}')
        time_diff = timezone.now() - self.instance.vcode_date #当前时间减去代码创建时间
        if time_diff.total_seconds() > 20 * 60:  #如果大于20分钟
            raise forms.ValidationError(_('验证码已超过20分钟,请重新获取'))
        vcode = self.cleaned_data.get('vcode')  #获取表单得到的数据段
        # 在这里进行验证码核验操作,与数据库中的 User 模型进行比对等           
        if vcode != self.instance.vcode:  #需在视图函数中传入instance=request.user才可去对比
            raise forms.ValidationError(_('验证码不正确'))  #返回错误信息
        #如果验证通过,则清空验证码
        #注意如果在表单和视图中同时执行了保存,则表单保存会失效
        self.instance.vcode = None  # 清空验证码
        self.instance.save()  # 保存修改
        return vcode

视图函数:

#待邮箱验证视图
@login_required 
@user_passes_test(v_email,login_url="/")
def active_view(request,diqu):
    if request.method == 'POST':
        form = VEmailForm(request.POST,instance=request.user)
        if form.is_valid():
            #先预保存,获得对象
            user = form.save(commit=False)
            user.is_email = True
            user.save()    
    else:
        form = VEmailForm(instance=request.user)#将用户传instance
    return render(request, 'active.html', {'form': form})

自己定义样式模板引用

<form method="POST">
    {% csrf_token %}
    {{ form.vcode }}
    {{ form.vcode.errors }}
    <button class="button is-dark is-fullwidth" type="submit">提交验证</button>
</form>

自己定义错误提示

{% if form.vcode.errors %}
    <ol>
    {% for error in form.vcode.errors %}
        <li><strong class="dd">{{ error|escape }}</strong></li>
    {% endfor %}
    </ol>
{% endif %}

表单输出所有错误提示

<style>
.errorlist {
    color: rgb(206, 0, 0);
    font-weight: bold;
}
</style>
{{ form.non_field_errors }}

从表单中取用户信息并修改数据库

注意如果在表单和视图中同时执行了保存,则表单保存会失效
#通过表单获取用户模型
if form.is_valid():
    print('验证通过')
    user = form.save(commit=False)  #获取对象先不保存
    user.is_email = True
    user.save()