zoukankan      html  css  js  c++  java
  • Django—Form两种解决表单数据无法动态刷新的方法

    一、无法动态更新数据的实例

    1. 如下,数据库中创建了班级表和教师表,两张表的对应关系为“多对多”

     1 from django.db import models
     2 
     3 
     4 class Classes(models.Model):
     5     title = models.CharField(max_length=32)
     6 
     7 
     8 class Teacher(models.Model):
     9     name = models.CharField(max_length=32)
    10     t2c = models.ManyToManyField(Classes)
    models.py

    2. views的功能有查看、添加、编辑班级或教师表

     1 from django.shortcuts import render, redirect
     2 from school import models
     3 from django.forms import Form, fields, widgets
     4 
     5 
     6 #班级表单验证规则
     7 class ClsForm(Form):
     8     title = fields.RegexField('老男孩', error_messages={'invalid': '请以 老男孩 开头'})
     9 
    10 
    11 #教师表单验证规则
    12 class TchForm(Form):
    13     name = fields.CharField(max_length=16, min_length=2, widget=widgets.TextInput(attrs={'class': 'form-control'}))
    14     t2c = fields.MultipleChoiceField(
    15         choices=models.Classes.objects.values_list('id', 'title'),
    16         widget=widgets.SelectMultiple(attrs={'class': 'form-control'})
    17     )
    18 
    19 
    20 #查看班级列表
    21 def classes(request):
    22     cls_list = models.Classes.objects.all()
    23     return render(request, 'classes.html', {'cls_list': cls_list})
    24 
    25 
    26 #查看教师列表
    27 def teachers(request):
    28     tch_list = models.Teacher.objects.all()
    29     return render(request, 'teachers.html', {'tch_list': tch_list})
    30 
    31 
    32 #添加班级
    33 def add_cls(request):
    34     if request.method == 'GET':
    35         obj = ClsForm()
    36         return render(request, 'add_classes.html', {'obj': obj})
    37     else:
    38         obj = ClsForm(request.POST)
    39         if obj.is_valid():
    40             models.Classes.objects.create(**obj.cleaned_data)
    41             return redirect('/school/classes/')
    42         return render(request, 'add_classes.html', {'obj': obj})
    43 
    44 
    45 #添加教师
    46 def add_tch(request):
    47     if request.method == 'GET':
    48         obj = TchForm()
    49         return render(request, 'add_teacher.html', {'obj': obj})
    50     else:
    51         obj = TchForm(request.POST)
    52         if obj.is_valid():
    53             tc = obj.cleaned_data.pop('t2c')    # 获取教师任课班级id
    54             tch_obj = models.Teacher.objects.create(name=obj.cleaned_data['name'])  # 添加新教师姓名
    55             tch_obj.t2c.add(*tc)    # 添加新教师任课班级
    56             return redirect('/school/teachers/')
    57         return render(request, 'add_teacher.html', {'obj': obj})
    58 
    59 
    60 #编辑班级
    61 def edit_cls(request, nid):
    62     if request.method == 'GET':
    63         cls = models.Classes.objects.filter(id=nid).first()
    64         obj = ClsForm(initial={'title': cls.title})
    65         return render(request, 'edit_classes.html', {'nid': nid, 'obj': obj})
    66     else:
    67         obj = ClsForm(request.POST)
    68         if obj.is_valid():
    69             models.Classes.objects.filter(id=nid).update(**obj.cleaned_data)
    70             return redirect('/school/classes/')
    71         return render(request, 'edit_classes.html', {'nid': nid, 'obj': obj})
    72 
    73 
    74 #编辑教师
    75 def edit_tch(request, nid):
    76     if request.method == 'GET':
    77         tch = models.Teacher.objects.filter(id=nid).first()
    78         v = tch.t2c.values_list('id')   # 获取该教师任课班级的id
    79         cls_ids = list(zip(*v))[0] if list(zip(*v)) else []     # 格式化为列表类型
    80         obj = TchForm(initial={'name': tch.name, 't2c': cls_ids})
    81         return render(request, 'edit_teacher.html', {'nid': nid, 'obj': obj})
    82     else:
    83         obj = TchForm(request.POST)
    84         if obj.is_valid():
    85             tc = obj.cleaned_data.pop('t2c')    # 获取修改后的任课班级id
    86             # models.Teacher.objects.filter(id=nid).update(name=obj.cleaned_data['name'])     # 更新教师姓名方法1
    87             tch_obj = models.Teacher.objects.filter(id=nid).first()
    88             tch_obj.name = obj.cleaned_data['name']     # 更新教师姓名方法2
    89             tch_obj.save()
    90             tch_obj.t2c.set(tc)
    91             return redirect('/school/teachers/')
    92         return render(request, 'edit_teacher.html', {'nid': nid, 'obj': obj})
    views.py

    3. html文件

    classe:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>班级列表</title>
     6     <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
     7 </head>
     8 <body>
     9 <div style=" 700px; margin: 30px auto">
    10     <a class="btn btn-default" href="/school/add_cls/" style="margin-bottom: 10px">添加班级</a>
    11         <table class="table table-hover" border="1" cellspacing="0">
    12             <thead>
    13             <tr>
    14                 <th>ID</th>
    15                 <th>班级</th>
    16                 <th>操作</th>
    17             </tr>
    18             </thead>
    19             <tbody>
    20                 {% for item in cls_list %}
    21                     <tr>
    22                         <td>{{ item.id }}</td>
    23                         <td>{{ item.title }}</td>
    24                         <td><a href="/school/edit_cls/{{ item.id }}">编辑</a></td>
    25                     </tr>
    26                 {% endfor %}
    27             </tbody>
    28         </table>
    29 </div>
    30 </body>
    31 </html>
    classes.html
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>添加班级</title>
     6 </head>
     7 <body>
     8 <h1>添加班级</h1>
     9 <form action="/school/add_cls/" method="post">
    10     {% csrf_token %}
    11     <p>
    12         {{ obj.title }} {{ obj.errors.title.0 }}
    13     </p>
    14     <input type="submit" value="提交">
    15 </form>
    16 </body>
    17 </html>
    add_classes.html
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>编辑班级</title>
     6 </head>
     7 <body>
     8 <h1>编辑班级</h1>
     9 <form action="/school/edit_cls/{{ nid }}" method="post">
    10     {% csrf_token %}
    11     <p>
    12         {{ obj.title }} {{ obj.errors.title.0 }}
    13     </p>
    14     <input type="submit" value="提交">
    15 </form>
    16 </body>
    17 </html>
    edit_classes.html

     teachers:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>教师列表</title>
     6     <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
     7 </head>
     8 <body>
     9 <div style=" 700px; margin: 30px auto">
    10     <a class="btn btn-default" href="/school/add_tch/" style="margin-bottom: 10px">添加教师</a>
    11         <table class="table table-hover" border="1" cellspacing="0">
    12             <thead>
    13             <tr>
    14                 <th>ID</th>
    15                 <th>姓名</th>
    16                 <th>任教班级</th>
    17                 <th>操作</th>
    18             </tr>
    19             </thead>
    20             <tbody>
    21                 {% for item in tch_list %}
    22                     <tr>
    23                         <td>{{ item.id }}</td>
    24                         <td>{{ item.name }}</td>
    25                         <td>
    26                             {% for row in item.t2c.all %}
    27                                 <span style="border: solid gray 1px">{{ row.title }}</span>
    28                             {% endfor %}
    29                         </td>
    30                         <td><a href="/school/edit_tch/{{ item.id }}">编辑</a></td>
    31                     </tr>
    32                 {% endfor %}
    33             </tbody>
    34         </table>
    35 </div>
    36 </body>
    37 </html>
    teachers.html
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>添加教师</title>
     6     <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
     7 </head>
     8 <body>
     9 <div style=" 500px; margin: 20px auto">
    10 <h3 style=" 100px; margin: 10px auto">添加教师</h3>
    11     <form class="form-horizontal" action="/school/add_tch/" method="post">
    12         {% csrf_token %}
    13   <div class="form-group">
    14     <label class="col-sm-2 control-label">姓名</label>
    15     <div class="col-sm-10">
    16       {{ obj.name }} {{ obj.errors.name.0 }}
    17     </div>
    18   </div>
    19   <div class="form-group">
    20     <label class="col-sm-2 control-label">班级</label>
    21     <div class="col-sm-10">
    22             {{ obj.t2c }} {{ obj.errors.t2c.0 }}
    23     </div>
    24   </div>
    25   <div class="form-group">
    26     <div class="col-sm-offset-2 col-sm-10">
    27       <input type="submit" class="btn btn-default" value="提交"></input>
    28     </div>
    29   </div>
    30 </form>
    31 </div>
    32 </body>
    33 </html>
    add_teacher.html
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>编辑教师</title>
     6     <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
     7 </head>
     8 <body>
     9 <div style=" 500px; margin: 20px auto">
    10 <h3 style=" 100px; margin: 10px auto">编辑教师</h3>
    11     <form class="form-horizontal" action="/school/edit_tch/{{ nid }}" method="post">
    12         {% csrf_token %}
    13   <div class="form-group">
    14     <label class="col-sm-2 control-label">姓名</label>
    15     <div class="col-sm-10">
    16       {{ obj.name }} {{ obj.errors.name.0 }}
    17     </div>
    18   </div>
    19 
    20   <div class="form-group">
    21     <label class="col-sm-2 control-label">班级</label>
    22     <div class="col-sm-10">
    23             {{ obj.t2c }} {{ obj.errors.t2c.0 }}
    24     </div>
    25   </div>
    26   <div class="form-group">
    27     <div class="col-sm-offset-2 col-sm-10">
    28       <input type="submit" class="btn btn-default" value="提交"></input>
    29     </div>
    30   </div>
    31 </form>
    32 </div>
    33 </body>
    34 </html>
    edit_teacher.html

    4. 数据不能同步

    在班级表中新增一条记录

    在教师表中新添加一名教师,发现无法获取上一步新增记录

    5. 原因分析

    在添加教师时,请求方式为GET,html标签由Form组件自动生成,其中的数据也是由Form组件提供

    而TchForm作为一个类,在project运行起来后,其中的name和t2c字段都是类的变量,其只执行一次,就将数据保存在内存中,无论之后生成多少个TchForm对象,其中的字段的值都不变。

    所以会出现教师表中的班级多选列表无法动态更新。

    二、解决上述bug的方法

    每次更新数据库后重启project,让Form类重新初始化,能够让数据更新,但这显然是不切实际的。

    知道了bug的根源,我们可以尝试让每次生成TchForm对象时就更新数据:

    方法一

    1. 利用 __init__将数据库操作放入对象变量中

     1 #教师表单验证规则
     2 class TchForm(Form):
     3     name = fields.CharField(max_length=16, min_length=2, widget=widgets.TextInput(attrs={'class': 'form-control'}))
     4     t2c = fields.MultipleChoiceField(
     5         # choices=models.Classes.objects.values_list('id', 'title'),
     6         widget=widgets.SelectMultiple(attrs={'class': 'form-control'})
     7     )
     8 
     9     def __init__(self, *args, **kwargs):    # 自定义__init__
    10         super(TchForm, self).__init__(*args, **kwargs)  # 调用父类的__init__
    11         self.fields['t2c'].choices = models.Classes.objects.values_list('id', 'title')   # 为字段t2c的choices赋值
    修改TchForm类

    2. 验证

     在班级表中新增一条记录

     再在教师表中添加

    方法二

    1. 利用django.forms.models模块中的queryset连接数据库

     1 #教师表单验证规则
     2 from django.forms import models as form_models  # 导入django.forms.models
     3 class TchForm(Form):
     4     name = fields.CharField(max_length=16, min_length=2, widget=widgets.TextInput(attrs={'class': 'form-control'}))
     5     #重新定义字段
     6     t2c = form_models.ModelMultipleChoiceField(
     7         # choices=models.Classes.objects.values_list('id', 'title'),
     8         queryset=models.Classes.objects.all(),  # 利用queryset连接数据库,只能连接object类型
     9         widget=widgets.SelectMultiple(attrs={'class': 'form-control'})
    10     )
    修改TchForm类

    2. 验证

    由于TchForm类中,queryset只能连接object类型,所以,需要设置models.py中的Classes类的返回值。

    1 class Classes(models.Model):
    2     title = models.CharField(max_length=32)
    3 
    4     def __str__(self):
    5         return self.title
    设置models.py中的Classes类的返回值

    在班级表中新增一条记录

    再在教师表中添加

  • 相关阅读:
    TC字符界面菜单程序【原创】
    图片定时自动播放
    根据登录的不同权限,登录不同的窗口!
    html布局
    sprig 的基本使用方法和运用领域
    hibernate的链接数据库的基本步骤
    Jquery
    Java链接数据库的基本步骤
    ajax
    SQL索引的初步使用
  • 原文地址:https://www.cnblogs.com/OldJack/p/7121510.html
Copyright © 2011-2022 走看看