Django—Form、ModelForm


一、Form

form.py

from django import forms
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
import re


# 定义手机号验证规则
def phone_validate(value):
    phone = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not phone.match(value):
        raise ValidationError("手机号格式错误")


class RegForm(forms.Form):
    username = forms.CharField(
        label="用户名",
        min_length=6,
        initial="请输入用户名",
        error_messages={
            'required': "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短6位"
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"})
    )

    password = forms.CharField(
        label="密码",
        min_length=8,
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),
        error_messages={
            "required": "不能为空",
            "min_length": "不能少于8位"
        }
    )

    re_password = forms.CharField(
        label="密码",
        min_length=8,
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),
        error_messages={
            "required": "不能为空",
            "min_length": "不能少于8位"
        }
    )

    email = forms.EmailField(
        label="邮箱",
        widget=forms.widgets.TextInput(attrs={"class": "form-control"}),
        error_messages={
            'required': "不能为空",
            "invalid": "格式错误",
        }
    )

    # radio
    gender = forms.fields.ChoiceField(
        choices=((1,""),(0,""),),
        label="性别",
        initial=1,
        widget=forms.widgets.RadioSelect()
    )

    # 单选select
    se_hobby = forms.fields.ChoiceField(
        label="select单选爱好",
        choices=((1,"篮球"),(2,"网球"),(3,"羽毛球"),),
        # initial=1,
        widget=forms.widgets.Select()
    )

    # 多选select
    se_hobbys = forms.fields.MultipleChoiceField(
        label="select多选爱好",
        choices=((1, "篮球"), (2, "网球"), (3, "羽毛球"),),
        initial=[1,],
        widget=forms.widgets.SelectMultiple()
    )

    # 单选checkbox
    keep_username = forms.fields.ChoiceField(
        label="记住用户名",
        # initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

    # 多选checkbox
    ch_hobbys = forms.fields.MultipleChoiceField(
        label="checkbox多选爱好",
        choices=((1, "篮球"), (2, "网球"), (3, "羽毛球"),),
        # initial=[1, 2],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

    # 手机号
    phone = forms.fields.CharField(
        validators=[phone_validate, ],
        error_messages={
            "required": "手机不能为空"
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"})
    )

    # # 批量增加样式
    # def __init__(self, *args, **kwargs):
    #     super(RegForm, self).__init__(*args, **kwargs)
    #     for field in iter(self.fields):
    #         self.fields[field].widget.attrs.update({
    #             'class': 'form-control'
    #         })
    # 
    #     # 动态获取数据库的choice数据
    #     self.fields["gender"].choices = User.objects.all().values_list("id", "gender")


    # 重写全局的钩子函数,对确认密码做校验
    def clean(self):
        password = self.cleaned_data.get("password")
        re_password = self.cleaned_data.get("re_password")
        if re_password and re_password != password:
            self.add_error("re_password", ValidationError("两次输入的密码不一致"))
        else:
            return self.cleaned_data

    # 定义局部钩子,验证用户名是否被注册
    def clean_username(self):
        username = self.cleaned_data.get("username")
        is_exist = User.objects.filter(username=username)
        if is_exist:
            self.add_error("username", ValidationError("用户名已被注册"))
        else:
            return username

    # 定义局部钩子,验证邮箱是否可用
    def clean_email(self):
        email = self.cleaned_data.get("email")
        is_exist = User.objects.filter(email=email)
        if is_exist:
            self.add_error("email", ValidationError("邮箱不可用"))
        else:
            return email

view.py

def reg(request):
    form_obj = RegForm()
    if request.method == "POST":
        ret = {"status": 0, "msg": ""}
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():
            # form_obj.cleaned_data.pop("re_password")
            # print(form_obj.cleaned_data)
            # User.objects.create_user(**form_obj.cleaned_data)
            ret["msg"] = "/login"
            return JsonResponse(ret)
        else:
            # print(form_obj.errors)
            ret["status"] = 1
            ret["msg"] = form_obj.errors
            return JsonResponse(ret)
    return render(request, 'register.html', {"forms_obj": form_obj})

register.html


"zh-CN">

    "UTF-8">
    Title
    'Content-type' content='text/htm'>
    "stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    
    


class="container">
class="row">
class="col-md-6 col-md-offset-3 reg-form">

class="text-center">Register


class="form-horizontal" novalidate method="post" enctype="multipart/form-data"> {% csrf_token %}
class="form-group ">
class="col-sm-8"> {{ forms_obj.username }} class="help-block">{{ forms_obj.username.errors.0 }} "ss" class="help-block">
class="form-group ">
class="col-sm-8"> {{ forms_obj.password }} class="help-block">{{ forms_obj.password.errors.0 }}
class="form-group ">
class="col-sm-8"> {{ forms_obj.re_password }} class="help-block">{{ forms_obj.re_password.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.email }} class="help-block">{{ forms_obj.email.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.gender }} class="help-block">{{ forms_obj.gender.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.se_hobby }} class="help-block">{{ forms_obj.se_hobby.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.se_hobbys }} class="help-block">{{ forms_obj.se_hobbys.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.keep_username }} class="help-block">{{ forms_obj.keep_username.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.ch_hobbys }} class="help-block">{{ forms_obj.ch_hobbys.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.phone }} class="help-block">{{ forms_obj.phone.errors.0 }}
class="form-group">
class="col-sm-offset-3 col-sm-6">

二、ModelForm

form.py

from booktest.models import *
from django.forms import widgets as wds


class BookForm(forms.ModelForm):
    class Meta:
        model = BookInfo
        fields = "__all__"
        labels = {
            "btitle": "书名",
            "bpub_date": "发布日期",
            "bcomment": "评论量",
            "bread": "阅读量"
        }

        widgets = {
            "btitle": wds.TextInput(attrs={"class": "form-control"}),
            "bpub_date": wds.TextInput(attrs={"class": "form-control", "type": "date"}),
            "bread": wds.TextInput(attrs={"class": "form-control"}),
            "bcomment": wds.TextInput(attrs={"class": "form-control"})
        }

        error_messages = {
            "btitle": {"required":"不能为空",},
            "bpub_date": {"required":"不能为空",},
            "bcomment": {"required":"不能为空",},
            "bread": {"required":"不能为空",}
        }

view.py(add_book)

def add_book(request):
    form_obj = BookForm()
    if request.method == "POST":
        ret = {"status": 0, "msg": ""}
        form_obj = BookForm(data=request.POST)
        if form_obj.is_valid():
            print(form_obj.cleaned_data)
            form_obj.save()
            ret["msg"] = '/bookform'
            return JsonResponse(ret)
        else:
            ret["status"] = 1
            ret["msg"] = form_obj.errors
            return JsonResponse(ret)
    return render(request, 'add_book.html', {"forms_obj": form_obj})

add_book.html


"zh-CN">

    "UTF-8">
    Title
    'Content-type' content='text/htm'>
    "stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    
    


class="container">
class="row">
class="col-md-6 col-md-offset-3 reg-form">

class="text-center">


class="form-horizontal" novalidate method="post" enctype="multipart/form-data"> {% csrf_token %}
class="form-group ">
class="col-sm-8"> {{ forms_obj.btitle }} class="help-block">{{ forms_obj.btitle.errors.0 }} "ss" class="help-block">
class="form-group ">
class="col-sm-8"> {{ forms_obj.bpub_date }} class="help-block">{{ forms_obj.bpub_date.errors.0 }}
class="form-group ">
class="col-sm-8"> {{ forms_obj.bcomment }} class="help-block">{{ forms_obj.bcomment.errors.0 }}
class="form-group">
class="col-sm-8"> {{ forms_obj.bread }} class="help-block">{{ forms_obj.bread.errors.0 }}
class="form-group">
class="col-sm-offset-3 col-sm-6">

view.py(edit_book)

def editbook(request, book_id):
    edit_book = BookInfo.objects.get(id=book_id)
    if request.method == "POST":
        form_obj = BookForm(request.POST, instance=edit_book)
        if form_obj.is_valid():
            form_obj.save()     # edit_book.update(request.POST)
            return redirect('/add_book')
    else:
        form_obj = BookForm(instance=edit_book)
        return render(request, 'edit_book.html', locals())

edit_book.html


"post"> {% csrf_token %} {% for field in form_obj %}
{{ field.label }} {{ field }}{{ field.errors.0 }}
{% endfor %} "submit">