【Django】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)
11
12 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})
93
94 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="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>
32
33 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>
18
19 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>
18
19 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="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>
38
39 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="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>
34
35 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="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>
35
36 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赋值
12
13 修改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     )
11
12 修改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

在班级表中新增一条记录

再在教师表中添加

原文:http://www.cnblogs.com/OldJack/p/7121510.html

时间: 2024-10-11 13:30:03

【Django】Django—Form两种解决表单数据无法动态刷新的方法的相关文章

两种解决IE6不支持固定定位的方法

有两种让IE6支持position:fixed1.用CSS执行表达式 *{margin:0;padding:0;} * html,* html body{ background-image:url(about:blank); background-attachment:fixed; } * html .fixed{ position:absolute; bottom:auto; top:expression(eval(document.documentElement.scrollTop+ doc

OGG的Director web hang住的两种解决方法

OGG的Director web hang住的两种解决方法: OGG的Director web hang住的解释:是指web界面能登陆进去,但是看得刷新日期是很久之前的日期,并且该日期不变化. OGG的Director web hang住 的情况之一: 参考如下的mos文章: Director web displaying "Error 500-Internal Server Error". Domain log has Cannot open paging store. (Doc I

ListView+CheckBox两种解决方式及原因分析

近期在用ListView+CheckBox搞一个item选中的项目,我将CheckBox的focus设置为false,另我大喜的是,CheckBox居然能够选中(窃喜中),这么简单就搞定了,由于数据量较小,也没有发现什么问题. 后来数据多了. 页面须要滑动了, 发现了一个奇怪的问题,前面明明选中了,而再次滑动回去的时候居然变成未选中状态! 这是我刚開始写的那段错误的代码: @Override public View getView(int position, View convertView,

Eclipse 安装 ADT 失败的两种解决办法 [Android Development Tooling]

原因 最近想在新装的 Win7 里搭建一下 Android 的开发环境,虽然现在有 Android Studio 了,不过还是习惯 Eclipse 一点.众所周知的原因,Eclipse 直接安装 ADT(Android Develepment Tooling) 插件是不行的,这里给出两种解决办法,我们的前提是要先安装 Google 的 翻[email protected]!墙工具 GoAgent . 一.使用 Proxy 由于直接访问是不行的,所以你可以使用 VPN 或者 GoAgent 做为

java.lang.IllegalArgumentException: pointerIndex out of range两种解决办法

java.lang.IllegalArgumentException: pointerIndex out of range 在做拍摄海报功能的时候需要拍摄界面的surface进行手势缩放,做多点触控放大缩小,操作时发生这个异常,如果是操作图片的放大缩小多点触控不会出现这个错误,这个bug是Android系统原因此处给出两种解决方式: 第一种方式是: 修改frameworks\base\core\jni\android_view_MotionEvent.cpp的android_view_Motio

[转] 两种自定义表单设计方案

无涯 原文 两种自定义表单设计方案 [原创] 2006-12 最近参与一个项目,客户要求提供自定义表单的功能.主要的要求是:能够对表单的字段进行增删改,对显示表单的格式可以灵活定制.由于客户的表单变动可能比较频繁,所以决定实现自定义表单功能.初步设想出以下两种自定义表单的解决方案,目前只涉及到表单的显示方案. 请大家讨论一下两种方案的优劣,使用哪种较好.也欢迎大家提出更好的解决方案. HTML模板方案 概述:采用HTML模板方式.对于每一种样式的表单定义HTML模板:在模板中定义Web页面的HT

ASP+中文显示之两种解决方法

作者刚开始写ASP+程序时候碰到的第一个比较大的问题就是中文显示问题,运行后发现ASP+从数据库中读 取出来的中文全部变成了?????,有点类似jsp中的这个频率出现最高的中文显示问题了,查了资料发现有 两种方法可以轻松解决中文问题. 方法一: 在翻阅了微软NGWS文档后发现在文档的常见问题部分有提到要添加一个config.web文件到 web目录下,试了一下,中文显示果然OK了. 方法如下: 建立一个文件config.web,内容如下,放在WEB目录下 <configuration> <

解决jquery中动态新增的元素节点无法触发事件的问题有两种解决方法

解决jquery中动态新增的元素节点无法触发事件的问题有两种解决方法,如下: 为了达到更好的演示效果,假设在某个页面的body下有以下结构的代码: ? 1 2 3 4 5 6 7 8 9 10 11 <p id="pLabel">新加一条</p> <ul id="ulLabel">  <li class="liLabel">aaa1</li>  <li class="li

OK6410 无法rmmod卸载模块 两种解决办法

OK6410  无法rmmod卸载模块  两种解决办法 这个问题一度让我觉得很奇怪... 可以看出我怎么rmmod都没用,那个模块就在那里...我换用了rmmod_by_EOF就没事了~ 方法一: 这个开发板自带文件系统的rmmod命令不行,在好心bloger的帮助下,自己重新编译一个 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include