Django的form组件

forms组件

forms组件,是一个类。在视图函数中创建一个类,类需要继承forms.Form

from django import  forms

1.校验数据

步骤和语法:

  1. 创建一个forms类,该类需继承forms.Form  , 得到一个类(假设为EmpForm),用于校正数据

  2.把用户信息传给ef=EmpForm(request.POST),得到一个form对象ef(传入的数据必须为字典)

  3. ef.is_valid()  ,数据都合格为True ,否则为False

  4.ef.is_valid()之后可以获取两部分数据:

    ef.cleand_data  获取合格后的数据,为字典

    ef.errors 不合格数据以及错误信息

  

model.py 文件中:

from django.db import models

# Create your models here.

class Emp(models.Model):
    name =models.CharField(max_length=32) #后面跟的是约束对象
    age =models.IntegerField()
    salary =models.DecimalField(max_digits=8,decimal_places=2)

视图函数中:

from django.shortcuts import render,HttpResponse,redirect
from aap1 import models
# Create your views here.
from django import forms
#forms 组件是一个类,对数据进行校正,下面是分别对name,age 字段进行较正
class EmpForm(forms.Form):
    #且所有要校正的字段必须为非空,否则会报错
    name = forms.CharField(max_length=5)  #name需要校验的字段 ,forms. 后面跟的是规则对象,此处为CharField()
    age = forms.IntegerField() #此校验规则,必须为一个数字



def addemp(request): if request.method=="GET": return render(request,"add.html") else: #获取字段值 # name =request.POST.get("name") # age =request.POST.get("age") # salary =request.POST.get("salary") # # 类 ,操作简单,耦合性比较好 ef = EmpForm(request.POST) #得到一个form对象 if ef.is_valid(): print(ef.cleaned_data) #得到校正合格之后的数据,也是一个字典 models.Emp.objects.create(**ef.cleaned_data) #传入一个字典,但是这样创建的话,需要将Emp中所有字段都进行校验或默认 else: print(ef.errors) #得到错误信息字典 return HttpResponse("ok")

2.渲染页面

models.py文件中:

from
django.db import models # Create your models here. class Emp(models.Model): name =models.CharField(max_length=32) #后面跟的是约束对象 age =models.IntegerField() salary =models.DecimalField(max_digits=8,decimal_places=2)
#后端views.py 文件中:(form组件的构建)

from django import forms
from django.core.exceptions import ValidationError
#forms 组件是一个类,创建一个需要渲染或检验的form组件 class EmpForm(forms.Form): #且所有要校正的字段必须为非空,否则会报错 name = forms.CharField(max_length=5,label="姓名",error_messages={"required":"该字段不能为空"}) #name需要校验的字段 ,forms. 后面跟的是规则对象,此处为CharField() age = forms.IntegerField(label="年龄") #此校验规则,必须为一个数字 salary=forms.CharField(label="薪水")
#视图函数,
def
addemp(request): if request.method=="GET": form =EmpForm() return render(request,"add.html",locals()) # locals(),将form 中所有的字段都可以传给前端页面进行渲染 else: #post请求得到,request.post 接收到前端传来的数据中的key必须和form组件中的字段名一样,不然无法进行校正,也就不能像下面一样传值 form = EmpForm(request.POST) #得到一个form对象 if form.is_valid(): #校正通过 print(form.cleaned_data) #得到干净的数据 models.Emp.objects.create(**form.cleaned_data) #数据干净后创建员工 return HttpResponse("添加成功") else:
        #校正没通过后向前端显示错误信息
print(form.errors) return render(request,"add.html",{"form":form})

渲染方式一:

<h3>渲染方式1</h3>
<form action="">
    {% csrf_token %}
    {{ form.as_p }}   #   
    <input type="submit">
</form>

渲染后:

<h3>渲染方式1</h3>
<form action="">
    <input type="hidden" name="csrfmiddlewaretoken" value="85HSKETnbwtkVgBId2g0eZ0GFmGoYqZ2oPcvdUQmupCH8hiWPFRWMsoXw7EV9YEb">
    <p><label for="id_name">姓名:</label> <input type="text" name="name" maxlength="5" required id="id_name"></p>
   <p><label for="id_age">年龄:</label> <input type="number" name="age" required id="id_age"></p>
   <p><label for="id_salary">薪水:</label> <input type="text" name="salary" required id="id_salary"></p>
    <input type="submit">
</form>

页面效果:

渲染方式二:

前端代码:

<h3>渲染方式2</h3>
<form action="">
    {% csrf_token %}
    <div>
        <label for="">姓名</label>
        {{ form.name }}
    </div>
     <div>
        <label for="">年龄</label>
        {{ form.age }}
    </div>
     <div>
        <label for="">薪水</label>
        {{ form.salary }}
    </div>

    <input type="submit">
</form>

渲染后:

<h3>渲染方式2</h3>
<form action="">
    <input type="hidden" name="csrfmiddlewaretoken" value="85HSKETnbwtkVgBId2g0eZ0GFmGoYqZ2oPcvdUQmupCH8hiWPFRWMsoXw7EV9YEb">
    <div>
        <label for="">姓名</label>
        <input type="text" name="name" maxlength="5" required id="id_name">
    </div>
     <div>
        <label for="">年龄</label>
        <input type="number" name="age" required id="id_age">
    </div>
     <div>
        <label for="">薪水</label>
        <input type="text" name="salary" required id="id_salary">
    </div>

    <input type="submit">
</form>

页面效果:

渲染方式三:

<h3>渲染方式3</h3>
<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for flied in form %}
    <div>
        <label for="">{{ flied.label }}</label>
        {{ flied }} <span>{{ flied.errors.0 }}</span>
    </div>
    {% endfor %}
    <input type="submit">
</form>

渲染后:

<h3>渲染方式3</h3>
<form action="" method="post" novalidate>
    <input type="hidden" name="csrfmiddlewaretoken" value="85HSKETnbwtkVgBId2g0eZ0GFmGoYqZ2oPcvdUQmupCH8hiWPFRWMsoXw7EV9YEb">
    
    <div>
        <label for="">姓名</label>
        <input type="text" name="name" maxlength="5" required id="id_name"> <span></span>
    </div>
    
    <div>
        <label for="">年龄</label>
        <input type="number" name="age" required id="id_age"> <span></span>
    </div>
    
    <div>
        <label for="">薪水</label>
        <input type="text" name="salary" required id="id_salary"> <span></span>
    </div>
    
    <input type="submit">
</form>

效果图:

3.显示错误与重置输入信息功能

视图:

def register(request):

    if request.method=="POST":
        form=UserForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)       # 所有干净的字段以及对应的值
        else:
            print(form.cleaned_data)       #
            print(form.errors)             # ErrorDict : {"校验错误的字段":["错误信息",]}
            print(form.errors.get("name")) # ErrorList ["错误信息",]
        return render(request,"register.html",locals())
    form=UserForm()
    return render(request,"register.html",locals())

模板:

<form action="" method="post" novalidate>
    {% csrf_token %}
    
    {% for field in form %}
        <div>
            <label for="">{{ field.label }}</label>
            {{ field }} <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
        </div>
    {% endfor %}
    <input type="submit" class="btn btn-default">

</form>

4.局部钩子与全局钩子

视图

# forms组件
from django.forms import widgets

wid_01=widgets.TextInput(attrs={"class":"form-control"})
wid_02=widgets.PasswordInput(attrs={"class":"form-control"})

from django.core.exceptions import ValidationError
class UserForm(forms.Form):
    name=forms.CharField(max_length=32,
                         widget=wid_01
                         )
    pwd=forms.CharField(max_length=32,widget=wid_02)
    r_pwd=forms.CharField(max_length=32,widget=wid_02)
    email=forms.EmailField(widget=wid_01)
    tel=forms.CharField(max_length=32,widget=wid_01)


    # 局部钩子
    def clean_name(self):
        val=self.cleaned_data.get("name")
        if not val.isdigit():
            return val
        else:
            raise ValidationError("用户名不能是纯数字!")

    # 全局钩子

    def clean(self):
        pwd=self.cleaned_data.get("pwd")
        r_pwd=self.cleaned_data.get("r_pwd")

        if pwd==r_pwd:
            return self.cleaned_data
        else:
            raise ValidationError('两次密码不一致!')


def register(request):

    if request.method=="POST":
        form=UserForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)       # 所有干净的字段以及对应的值
        else:
            clean_error=form.errors.get("__all__")

        return render(request,"register.html",locals())
    form=UserForm()
    return render(request,"register.html",locals())

模板

<form action="" method="post" novalidate>
            {% csrf_token %}

            {% for field in form %}
                <div>
                    <label for="">{{ field.label }}</label>
                    {{ field }}
                    <span class="pull-right" style="color: red">
                          {% if field.label == 'R pwd' %}
                          <span>{{ clean_error.0 }}</span>
                          {% endif %}
                          {{ field.errors.0 }}
                    </span>
                </div>
            {% endfor %}
            <input type="submit" class="btn btn-default">

</form>

 forms组件知识补充:

model用法:
  gender=models.IntegerField(choices=((1,""),(2,"")),default=1)
  alex=Author.objects.all().first()
  
alex.gender
# 1 alex.get_gender_display() # "男" forms用法: # Create your models here. class Book(models.Model): title = models.CharField( max_length=32) pub_date=models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2) state=models.IntegerField(choices=((1,"已出版"),(2,"未出版")),default=1) publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE,null=True) authors=models.ManyToManyField("Author",db_table="book2authors") # 创建关系表 def __str__(self): return self.title # forms组件: from django import forms class BookForm(forms.Form): title=forms.CharField(max_length=32) price=forms.DecimalField(max_digits=5,decimal_places=2) pub_date=forms.DateField() state=forms.ChoiceField(choices=((1,"已出版"),(2,"未出版"))) #在前端的的效果 <option value=1>已出版<option> <option value=2>未出版<option> # publish=forms.ChoiceField(choices=list(models.Publish.objects.all().values_list("pk","name"))) publish=forms.ModelChoiceField(queryset=models.Publish.objects.all()) authors=forms.ModelMultipleChoiceField(queryset=models.Author.objects.all()) # modelForm class BookModelForm(forms.ModelForm): class Meta: model=models.Book # fields=["title","price"] # exclude = ["title"] fields="__all__" #ModelForm 参数配置 class BookModelForm(forms.ModelForm): class Meta: model=models.Book # fields=["title","price"] # exclude = ["title"] fields="__all__" #定义标签属性 widgets={ "title":wid.TextInput(attrs={"class":"form-control"}), "price":wid.TextInput(attrs={"class":"form-control"}) } error_messages={ "title":{"required":"该字段不能为空"} } labels={ "title":"书籍名称" } def clean_title(self): val=self.cleaned_data.get("title") if val.startswith("yuan"): return val else: raise ValidationError("必须以yuan开头!")
原文地址:https://www.cnblogs.com/knighterrant/p/10261126.html