Home >Backend Development >Python Tutorial >Share two methods to solve the problem that Form form data cannot be refreshed dynamically.

Share two methods to solve the problem that Form form data cannot be refreshed dynamically.

巴扎黑
巴扎黑Original
2017-07-24 15:37:382900browse

1. Instances where data cannot be updated dynamically

1. As shown below, the class table and teacher table are created in the database, and the corresponding relationship between the two tables is "many-to-many"

 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. The functions of views include viewing, adding, and editing class or teacher tables

 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')    # 获取教师任课班级id54             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')   # 获取该教师任课班级的id79         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')    # 获取修改后的任课班级id86             # models.Teacher.objects.filter(id=nid).update(name=obj.cleaned_data['name'])     # 更新教师姓名方法187             tch_obj = models.Teacher.objects.filter(id=nid).first()88             tch_obj.name = obj.cleaned_data['name']     # 更新教师姓名方法289             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 file

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?1.1.11"> 7 </head> 8 <body> 9 <div style="width: 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?1.1.11"> 7 </head> 8 <body> 9 <div style="width: 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?1.1.11"> 7 </head> 8 <body> 9 <div style="width: 500px; margin: 20px auto">10 <h3 style="width: 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?1.1.11"> 7 </head> 8 <body> 9 <div style="width: 500px; margin: 20px auto">10 <h3 style="width: 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类的返回值

在班级表中新增一条记录

再在教师表中添加

 

The above is the detailed content of Share two methods to solve the problem that Form form data cannot be refreshed dynamically.. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn