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
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta http-equiv='Content-type' content='text/htm'> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <script src="/static/jquery-3.3.1.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3 reg-form"> <h3 class="text-center">Register</h3><br> <form class="form-horizontal" novalidate method="post" enctype="multipart/form-data"> {% csrf_token %} <div class="form-group "> <label for='{{ forms_obj.username.id_for_label }}' class="col-sm-2 control-label">{{ forms_obj.username.label }}</label> <div class="col-sm-8"> {{ forms_obj.username }} <span class="help-block">{{ forms_obj.username.errors.0 }}</span> <span id="ss" class="help-block"></span> </div> </div> <div class="form-group "> <label for='{{ forms_obj.password.id_for_label }}' class="col-sm-2 control-label">{{ forms_obj.password.label }}</label> <div class="col-sm-8"> {{ forms_obj.password }} <span class="help-block">{{ forms_obj.password.errors.0 }}</span> </div> </div> <div class="form-group "> <label for='{{ forms_obj.re_password.id_for_label }}' class="col-sm-2 control-label">{{ forms_obj.re_password.label }}</label> <div class="col-sm-8"> {{ forms_obj.re_password }} <span class="help-block">{{ forms_obj.re_password.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.email.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.email.label }}</label> <div class="col-sm-8"> {{ forms_obj.email }} <span class="help-block">{{ forms_obj.email.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.gender.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.gender.label }}</label> <div class="col-sm-8"> {{ forms_obj.gender }} <span class="help-block">{{ forms_obj.gender.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.se_hobby.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.se_hobby.label }}</label> <div class="col-sm-8"> {{ forms_obj.se_hobby }} <span class="help-block">{{ forms_obj.se_hobby.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.se_hobbys.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.se_hobbys.label }}</label> <div class="col-sm-8"> {{ forms_obj.se_hobbys }} <span class="help-block">{{ forms_obj.se_hobbys.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.keep_username.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.keep_username.label }}</label> <div class="col-sm-8"> {{ forms_obj.keep_username }} <span class="help-block">{{ forms_obj.keep_username.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.ch_hobbys.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.ch_hobbys.label }}</label> <div class="col-sm-8"> {{ forms_obj.ch_hobbys }} <span class="help-block">{{ forms_obj.ch_hobbys.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.phone.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.phone.label }}</label> <div class="col-sm-8"> {{ forms_obj.phone }} <span class="help-block">{{ forms_obj.phone.errors.0 }}</span> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-6"> <button id="reg_submit" type="button" class="btn btn-success btn-block">注册</button> </div> </div> </form> </div> </div> </div> <script> $("#reg_submit").click(function () { var formData = new FormData(); formData.append("username", $("#id_username").val()); formData.append("password", $("#id_password").val()); formData.append("re_password", $("#id_re_password").val()); formData.append("gender", $("input[name='gender']:checked").val()); formData.append("se_hobby", $("#id_se_hobby").val()); formData.append("se_hobbys", $("#id_se_hobbys").val()); formData.append("keep_username", $("#id_keep_username").prop("checked")); formData.append("ch_hobbys", $("#id_ch_hobbys input[name='ch_hobbys']:checked").val()); formData.append("phone", $("#id_phone").val()); formData.append("csrfmiddlewaretoken", $("input[name='csrfmiddlewaretoken']").val()); $.ajax({ url:'/register/', type:'post', processData: false, contentType: false, data:formData, }).done(function (data) { if (data.status){ $.each(data.msg,function (k,v) { $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error") }) } else { window.location.href = data.msg } }) }); $("form input").focus(function () { $(this).next("span").text("").parent().parent().removeClass("has-error"); }); $("form select").focus(function () { $(this).next("span").text("").parent().parent().removeClass("has-error"); }); $("form input[name='ch_hobbys']").focus(function () { $(this).parents("ul").next("span").text("").parent().parent().removeClass("has-error"); }) </script> </body> </html>
二、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
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta http-equiv='Content-type' content='text/htm'> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <script src="/static/jquery-3.3.1.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3 reg-form"> <h3 class="text-center"></h3><br> <form class="form-horizontal" novalidate method="post" enctype="multipart/form-data"> {% csrf_token %} <div class="form-group "> <label for='{{ forms_obj.btitle.id_for_label }}' class="col-sm-2 control-label">{{ forms_obj.btitle.label }}</label> <div class="col-sm-8"> {{ forms_obj.btitle }} <span class="help-block">{{ forms_obj.btitle.errors.0 }}</span> <span id="ss" class="help-block"></span> </div> </div> <div class="form-group "> <label for='{{ forms_obj.bpub_date.id_for_label }}' class="col-sm-2 control-label">{{ forms_obj.bpub_date.label }}</label> <div class="col-sm-8"> {{ forms_obj.bpub_date }} <span class="help-block">{{ forms_obj.bpub_date.errors.0 }}</span> </div> </div> <div class="form-group "> <label for='{{ forms_obj.bcomment.id_for_label }}' class="col-sm-2 control-label">{{ forms_obj.bcomment.label }}</label> <div class="col-sm-8"> {{ forms_obj.bcomment }} <span class="help-block">{{ forms_obj.bcomment.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ forms_obj.bread.id_for_label }}" class="col-sm-2 control-label">{{ forms_obj.bread.label }}</label> <div class="col-sm-8"> {{ forms_obj.bread }} <span class="help-block">{{ forms_obj.bread.errors.0 }}</span> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-6"> <button id="reg_submit" type="button" class="btn btn-success btn-block">注册</button> </div> </div> </form> </div> </div> </div> <script> $("#reg_submit").click(function () { var formData = new FormData(); formData.append("btitle", $("#id_btitle").val()); formData.append("bpub_date", $("#id_bpub_date").val()); formData.append("bcomment", $("#id_bcomment").val()); formData.append("bread", $("#id_bread").val()); formData.append("csrfmiddlewaretoken", $("input[name='csrfmiddlewaretoken']").val()); $.ajax({ url:'/bookform/', type:'post', processData: false, contentType: false, data:formData, }).done(function (data) { if (data.status){ $.each(data.msg,function (k,v) { $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error") }) } else { window.location.href = data.msg } }) }); $("form input").focus(function () { $(this).next("span").text("").parent().parent().removeClass("has-error"); }); </script> </body> </html>
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
<body> <form method="post"> {% csrf_token %} {% for field in form_obj %} <div> {{ field.label }} {{ field }}<span>{{ field.errors.0 }}</span> </div> {% endfor %} <input type="submit"> </form> </body>