欢迎来到军工软件开发人才培养基地——学到牛牛

Django ModelForm组件使用

时间:2024-05-06 07:01:10 来源:学到牛牛

ModelForm组件是用于简化表单操作的组件,学习ModelForm组件最好的办法是通过与原生的Form表单进行对比,即可以体会到ModelForm的便利。

1、原生方式

使用原生的方式实现Form表单提交功能。以新建用户为例,首先在user_add.html页面中编写用户信息表单。

{% extends 'menu_template.html' %}

 

{% block menu %}

   {# 第二步:新建用户内容区 #}

   <div class="container">

      <div class="panel panel-default">

        <div class="panel-heading">新建用户</div>

         <div class="panel-body">

            {# 表单 #}

            <div class=col-md-10>

               <form class="form-horizontal" method="post">

                  {% csrf_token %}

 

                  {# 姓名 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">姓名</label>

                     <div class="col-sm-10">

                        <input type="text" class="form-control" id="inputEmail3" placeholder="姓名" name="name">

                     </div>

                  </div>

 

                  {# 密码 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">密码</label>

                     <div class="col-sm-10">

                        <input type="text" class="form-control" id="inputEmail3" placeholder="密码" name="password">

                     </div>

                  </div>

 

                  {# 年龄 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">年龄</label>

                     <div class="col-sm-10">

                        <input type="text" class="form-control" id="inputEmail3" placeholder="年龄" name="age">

                     </div>

                  </div>

 

                  {# 余额 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">余额</label>

                     <div class="col-sm-10">

                        <input type="text" class="form-control" id="inputEmail3" placeholder="余额" name="account">

                     </div>

                  </div>

 

                  {# 入职时间 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">入职时间</label>

                     <div class="col-sm-10">

                        <input type="text" class="form-control" id="inputEmail3" placeholder="入职时间" name="create_time">

                     </div>

                  </div>

 

                  {# 性别 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">性别</label>

                     <div class="col-sm-10">

                        <select name="gender" class="form-control">

                           <option value="1">男</option>

                           <option value="2">女</option>

                        </select>

                     </div>

                  </div>

 

                  {# 所属部门 #}

                  <div class="form-group">

                     <label for="inputEmail3" class="col-sm-2 control-label">所属部门</label>

                     <div class="col-sm-10">

                        <select name="depart" class="form-control">

                           <option value="0">请选择部门</option>

                           {% for obj in user_info %}

                              <option value="{{ obj.depart_id }}">{{ obj.depart.title }}</option>

                           {% endfor %}

                        </select>

                     </div>

                  </div>

 

 

 

                  <div class="form-group">

                     <div class="col-sm-offset-2 col-sm-10">

                        <button type="submit" class="btn btn-primary">保 存</button>

                     </div>

                  </div>

               </form>

            </div>

         </div>

      </div>

   </div>

{% endblock %}

 

在views.py文件编写user_add()函数,用于添加用户。

# 添加用户

def user_add(request):

   # 1、将请求转交到user_add.html页面

   if request.method == "GET":

      # 获取用户相关的信息

      user = models.UserInfo.objects.all()

      # 接收到请求后,跳转到用户添页面

      return render(request, "user_add.html", {"user_info": user})

 

   # 2、获取用户提交的数据

   if request.method == "POST":

      name = request.POST.get("name")

      password = request.POST.get("password")

      age = request.POST.get("age")

      account = request.POST.get("account")

      create_time = request.POST.get("create_time")

      gender = request.POST.get("gender")

      depart = request.POST.get("depart")

      print(name, password, age, account, create_time, gender, depart)

 

      # 3、将获取到的数据添加到数据库

      models.UserInfo.objects.create(name=name, password=password, age=age, account=account, create_time=create_time, gender=gender, depart_id=depart)

   # 4、数据插入后跳转到用户列表页面

   return redirect("/user/list/")

 

在urls.py文件添加访问新建用户的URL地址。

# 新建用户

path('user/add/', views.user_add)

 

 

不采用原始方式的本质是它比较麻烦。

① 用户提交的数据没有校验。原始方式需要拿到字段一个一个校验,校验工作量非常的大。

② 错误提示,如果出现错误,页面应该出现错误提示。

③ 页面上的每一个字段都需要我们重新写一遍,很费劲。

④ 关联的数据,需要手动获取,然后才能展示在展示在页面中。

 

Django中提供ModelForm组件帮助我们完善以上问题。

 

2、ModelForm组件

基于ModelForm组件实现新增用户功能。

ModelForm组件是最常用的表单组件。以后在Django中,只要涉及表单提交,就得使用ModelForm组件进行操作,它主要解决以下功能。

① 它可以直接将数据库中的数据给展示到HTML页面。

② 它可以对提交的数据进行校验。

③ 如果提交数据有误,提交后ModelForm组件不会清楚之前填写的数据,它会保留原来的数据,以便后期修改。

2.1 添加新增用户的URL地址

# 基于ModelForm的新增用户

path('user/model/form/add/', views.user_model_form_add),

 

2.2 在views.py文件中添加user_model_form_add()函数,并编写逻辑。

2.2.1 创建ModelForm类,并设置相关规则

# 使用ModelForm前,需要创建一个类,并继承ModelForm

from django import forms

 

# 创建一个自定义的ModelForm类,并继承ModelForm

class UserModelForm(forms.ModelForm):

   # ****** 定制校验规则 ******

   # Form中,自动校验是否为空,如果需要其它校验,需要重新定义

   # 例子追加了校验规则,对name字段进行校验,要求字符长度最小不低于2

   name = forms.CharField(label="用户名", min_length=2)

   

   # 第一步:设置Meta类

   # 每个模型类(Model)下,都有一个子类(Meta),这个子类就是用于定义元数据的类。

   # Meta类中封装了一些数据库的信息(称之为Model的元数据),Django会将Mate中的元数据选项定义附加到Model中,

   # 常见元数据据定义有db_table(数据表名称)、abstract(抽象类)、ordering(字段排序)等。

   class Meta:

      # 第二步:设置关联的类

      model = models.UserInfo

 

      # 第三步:设置相关字段

      # fields是设置字段名称列表,包括返回字段中的命名字段;如果省略则返回全部字段。

      fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]

      # 第四步:给关联字段生成的HTML标签设置属性

      # widgets用于设置映射在字段上的HTML属性

      # 1、手动为每个字段添加样式;可以在Django后台,定制控件,用于设置生成HTML时的属性。

      # widgets = {

      #    "name": forms.TextInput(attrs={"class": "form-control"}),

      #    "password": forms.PasswordInput(attrs={"class": "form-control"}),

      #    "age": forms.TextInput(attrs={"class": "form-control"}),

      #    "account": forms.NumberInput(attrs={"class": "form-control"}),

      #    "create_time": forms.TextInput(attrs={"class": "form-control"}),

      #    "gender": forms.TextInput(attrs={"class": "form-control"}),

      #    "depart": forms.TextInput(attrs={"class": "form-control"}),

      # }

 

   # 为简化第四步,可以使用重写构造函数的方式设置自动生成的HTML标签属性

   def __init__(self, *args, **kwargs):

      # 调用父类构造函数

      super().__init__(*args, **kwargs)

 

      # 2、循环为每个字段添加样式

      # 通过循环找到所有字段中的插件,并给所有字段加上class属性,就不需要手动的在widgets控件中一个一个的添加。

      # self.field.items():获取字段列表中所有元素

      for name, field in self.fields.items():

         field.widget.attrs = {

            "class": "form-control",

            "placeholder": field.label

         }

 

2.2.2 编写添加新用户逻辑

# 基于ModelForm组件添加新用户

def user_model_form_add(request):

   # 第一步:跳转到user_model_form_add.html(添加用户页面),并携带个字段的属性

   if request.method == "GET":

      # 在使用Form表格数据时,需要实例化ModelForm类,得到的Form对象即包含数据库中的数据。ModelForm类创建见2.2.1小节。

      form = UserModelForm()

          # 将获取到的数据,返回给user_model_form_add.html页面

      return render(request, "user_model_form_add.html", {"form": form})

 

   # 第二步:使用自定义的ModelForm类的实例,获取请求的数据

   # 接收前台提交的POST请求,然后进行校验

   # data=request.POST将请求数据与ModelForm类进行高度封装,从而获取Form表单对象

   form = UserModelForm(data=request.POST)

 

   # 第三步:判断请求数据的有效性

   if form.is_valid():

      print("获取POST提交的数据:", form.cleaned_data)

      # 第四步:如果有效,将数据保存到数据库

      # Meta类中提供save()方法,用于将请求数据保存到映射数据库中

      form.save()

      return redirect("/user/list/")

   else:

      # 第四步:如果无效,将Form表单数据再次返回给user_model_form_add.html页面,返回的数据中携带有错误信息。

      return render(request, "user_model_form_add.html", {"form": form})

 

2.3 在user_model_form_add.html页面中设置Form表单,用于收集数据和展示后台数据。

2.3.1 设置user_model_form_add.html页面

{% extends 'menu_template.html' %}

 

{% block menu %}

   {# 内容区 #}

   <div class="container">

      <div class="panel panel-default">

        <div class="panel-heading">新建部门</div>

         <div class="panel-body">

            {# 表单 #}

            <div class=col-md-10>

               {# 注意:使用ModelForm后,浏览器页面为我们提供表单自动校验功能,如果要自定义校验错误需要关闭浏览器自动校验,使用novalidate(关闭校验)即可 #}

               <form class="form-horizontal" method="post" novalidate>

                  {% csrf_token %}

          

                  {# form是后台传入的数据集,通过循环获取里面的每个对象 #}  

                  {% for field in form %}

                     <div class="form-group">

                       {# 使用xx.label可以获取标题,即models.py文件中定义的verbose_name属性,例如:verbose_name='姓名' #}

                        <label for="inputEmail3" class="col-sm-2 control-label">{{ field.label }}</label>

                       {# 使用field则可以获取每个字段的值。但是,在获取关联表中的字段时它获取的是关联表中每条数据的对象,要想获取字段需要重写str函数,详见2.3.2小节 #}

                        <div class="col-sm-10">

                           {{ field }}

                           {# <input type="text" class="form-control" id="inputEmail3" placeholder="{{ field.lable }}" name="title"> #}

                           {# 浏览器器为自动校验错误信息。如果想要获取错误信息,把它展示到HTML页面,可以使用errors属性获取,它封装了所有错误信息的数据集,如果要实现自已获取错误信息,需要关闭浏览器自动校验功能 #}

                           <span style="color: red">

                              {# 默认只能校验是否为空 #}

                              {# errors返回值为列表,我们只需要获取第1个错误即可 #}

                              {# 错误信息默认以英文形式显示,如果要显示中文,需要到settings.py中设置LANGUAGE_CODE = 'zh-hans',详见2.3.3小节 #}

                              {{ field.errors.0 }}

                           </span>

                        </div>

                     </div>

                  {% endfor %}

 

                  <div class="form-group">

                     <div class="col-sm-offset-2 col-sm-10">

                        <button type="submit" class="btn btn-primary">保 存</button>

                     </div>

                  </div>

               </form>

            </div>

         </div>

      </div>

   </div>

 

{% endblock %}

 

2.3.2 设置表模型

在models.py文件中,重写模型类的str函数,将需要的字段返回给调用者。

from django.db import models

 

 

# 部门表

class Department(models.Model):

   # verbose_name用于给字段进行备注

   title = models.CharField(verbose_name='标题', max_length=32)

 

   # 重写Department类的str方法,用于设置实例化对象时返回的数据(默认返回当前对象)

   def __str__(self):

      return self.title

 

2.3.3 设置中文输出

在settings.py文件中将LANGUAGE_CODE属性的值修改为zh-hans,则可以实现错误信息以中文方式显示。

LANGUAGE_CODE = 'zh-hans'