一、无法动态更新数据的实例
1. 如下,数据库中创建了班级表和教师表,两张表的对应关系为“多对多”
1
2
3
4
5
6
|
from django.db import models class Classes(models.Model): title = models.CharField(max_length = 32 ) class Teacher(models.Model): name = models.CharField(max_length = 32 ) t2c = models.ManyToManyField(Classes) |
2. views的功能有查看、添加、编辑班级或教师表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
from django.shortcuts import render, redirect from school import models from django.forms import Form, fields, widgets #班级表单验证规则 class ClsForm(Form): title = fields.RegexField( '老男孩' , error_messages = { 'invalid' : '请以 老男孩 开头' }) #教师表单验证规则 class TchForm(Form): name = fields.CharField(max_length = 16 , min_length = 2 , widget = widgets.TextInput(attrs = { 'class' : 'form-control' })) t2c = fields.MultipleChoiceField( choices = models.Classes.objects.values_list( 'id' , 'title' ), widget = widgets.SelectMultiple(attrs = { 'class' : 'form-control' }) ) #查看班级列表 def classes(request): cls_list = models.Classes.objects. all () return render(request, 'classes.html' , { 'cls_list' : cls_list}) #查看教师列表 def teachers(request): tch_list = models.Teacher.objects. all () return render(request, 'teachers.html' , { 'tch_list' : tch_list}) #添加班级 def add_cls(request): if request.method = = 'GET' : obj = ClsForm() return render(request, 'add_classes.html' , { 'obj' : obj}) else : obj = ClsForm(request.POST) if obj.is_valid(): models.Classes.objects.create( * * obj.cleaned_data) return redirect( '/school/classes/' ) return render(request, 'add_classes.html' , { 'obj' : obj}) #添加教师 def add_tch(request): if request.method = = 'GET' : obj = TchForm() return render(request, 'add_teacher.html' , { 'obj' : obj}) else : obj = TchForm(request.POST) if obj.is_valid(): tc = obj.cleaned_data.pop( 't2c' ) # 获取教师任课班级id tch_obj = models.Teacher.objects.create(name = obj.cleaned_data[ 'name' ]) # 添加新教师姓名 tch_obj.t2c.add( * tc) # 添加新教师任课班级 return redirect( '/school/teachers/' ) return render(request, 'add_teacher.html' , { 'obj' : obj}) #编辑班级 def edit_cls(request, nid): if request.method = = 'GET' : cls = models.Classes.objects. filter ( id = nid).first() obj = ClsForm(initial = { 'title' : cls .title}) return render(request, 'edit_classes.html' , { 'nid' : nid, 'obj' : obj}) else : obj = ClsForm(request.POST) if obj.is_valid(): models.Classes.objects. filter ( id = nid).update( * * obj.cleaned_data) return redirect( '/school/classes/' ) return render(request, 'edit_classes.html' , { 'nid' : nid, 'obj' : obj}) #编辑教师 def edit_tch(request, nid): if request.method = = 'GET' : tch = models.Teacher.objects. filter ( id = nid).first() v = tch.t2c.values_list( 'id' ) # 获取该教师任课班级的id cls_ids = list ( zip ( * v))[ 0 ] if list ( zip ( * v)) else [] # 格式化为列表类型 obj = TchForm(initial = { 'name' : tch.name, 't2c' : cls_ids}) return render(request, 'edit_teacher.html' , { 'nid' : nid, 'obj' : obj}) else : obj = TchForm(request.POST) if obj.is_valid(): tc = obj.cleaned_data.pop( 't2c' ) # 获取修改后的任课班级id # models.Teacher.objects.filter(id=nid).update(name=obj.cleaned_data['name']) # 更新教师姓名方法1 tch_obj = models.Teacher.objects. filter ( id = nid).first() tch_obj.name = obj.cleaned_data[ 'name' ] # 更新教师姓名方法2 tch_obj.save() tch_obj.t2c. set (tc) return redirect( '/school/teachers/' ) return render(request, 'edit_teacher.html' , { 'nid' : nid, 'obj' : obj}) |
3. html文件
classe:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>班级列表< / title> <link rel = "stylesheet" href = "/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" > < / head> <body> <div style = "width: 700px; margin: 30px auto" > <a class = "btn btn-default" href = "/school/add_cls/" rel = "external nofollow" style = "margin-bottom: 10px" >添加班级< / a> <table class = "table table-hover" border = "1" cellspacing = "0" > <thead> <tr> <th> ID < / th> <th>班级< / th> <th>操作< / th> < / tr> < / thead> <tbody> { % for item in cls_list % } <tr> <td>{{ item. id }}< / td> <td>{{ item.title }}< / td> <td><a href = "/school/edit_cls/{{ item.id }}" rel = "external nofollow" >编辑< / a>< / td> < / tr> { % endfor % } < / tbody> < / table> < / div> < / body> < / html> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>添加班级< / title> < / head> <body> <h1>添加班级< / h1> <form action = "/school/add_cls/" method = "post" > { % csrf_token % } <p> {{ obj.title }} {{ obj.errors.title. 0 }} < / p> < input type = "submit" value = "提交" > < / form> < / body> < / html> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>编辑班级< / title> < / head> <body> <h1>编辑班级< / h1> <form action = "/school/edit_cls/{{ nid }}" method = "post" > { % csrf_token % } <p> {{ obj.title }} {{ obj.errors.title. 0 }} < / p> < input type = "submit" value = "提交" > < / form> < / body> < / html> |
teachers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>教师列表< / title> <link rel = "stylesheet" href = "/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" > < / head> <body> <div style = "width: 700px; margin: 30px auto" > <a class = "btn btn-default" href = "/school/add_tch/" rel = "external nofollow" style = "margin-bottom: 10px" >添加教师< / a> <table class = "table table-hover" border = "1" cellspacing = "0" > <thead> <tr> <th> ID < / th> <th>姓名< / th> <th>任教班级< / th> <th>操作< / th> < / tr> < / thead> <tbody> { % for item in tch_list % } <tr> <td>{{ item. id }}< / td> <td>{{ item.name }}< / td> <td> { % for row in item.t2c. all % } <span style = "border: solid gray 1px" >{{ row.title }}< / span> { % endfor % } < / td> <td><a href = "/school/edit_tch/{{ item.id }}" rel = "external nofollow" >编辑< / a>< / td> < / tr> { % endfor % } < / tbody> < / table> < / div> < / body> < / html> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>添加教师< / title> <link rel = "stylesheet" href = "/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" > < / head> <body> <div style = "width: 500px; margin: 20px auto" > <h3 style = "width: 100px; margin: 10px auto" >添加教师< / h3> <form class = "form-horizontal" action = "/school/add_tch/" method = "post" > { % csrf_token % } <div class = "form-group" > <label class = "col-sm-2 control-label" >姓名< / label> <div class = "col-sm-10" > {{ obj.name }} {{ obj.errors.name. 0 }} < / div> < / div> <div class = "form-group" > <label class = "col-sm-2 control-label" >班级< / label> <div class = "col-sm-10" > {{ obj.t2c }} {{ obj.errors.t2c. 0 }} < / div> < / div> <div class = "form-group" > <div class = "col-sm-offset-2 col-sm-10" > < input type = "submit" class = "btn btn-default" value = "提交" >< / input > < / div> < / div> < / form> < / div> < / body> < / html> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>编辑教师< / title> <link rel = "stylesheet" href = "/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" rel = "external nofollow" > < / head> <body> <div style = "width: 500px; margin: 20px auto" > <h3 style = "width: 100px; margin: 10px auto" >编辑教师< / h3> <form class = "form-horizontal" action = "/school/edit_tch/{{ nid }}" method = "post" > { % csrf_token % } <div class = "form-group" > <label class = "col-sm-2 control-label" >姓名< / label> <div class = "col-sm-10" > {{ obj.name }} {{ obj.errors.name. 0 }} < / div> < / div> <div class = "form-group" > <label class = "col-sm-2 control-label" >班级< / label> <div class = "col-sm-10" > {{ obj.t2c }} {{ obj.errors.t2c. 0 }} < / div> < / div> <div class = "form-group" > <div class = "col-sm-offset-2 col-sm-10" > < input type = "submit" class = "btn btn-default" value = "提交" >< / input > < / div> < / div> < / form> < / div> < / body> < / html> |
4. 数据不能同步
在班级表中新增一条记录
在教师表中新添加一名教师,发现无法获取上一步新增记录
5. 原因分析
在添加教师时,请求方式为GET,html标签由Form组件自动生成,其中的数据也是由Form组件提供
而TchForm作为一个类,在project运行起来后,其中的name和t2c字段都是类的变量,其只执行一次,就将数据保存在内存中,无论之后生成多少个TchForm对象,其中的字段的值都不变。
所以会出现教师表中的班级多选列表无法动态更新。
二、解决上述bug的方法
每次更新数据库后重启project,让Form类重新初始化,能够让数据更新,但这显然是不切实际的。
知道了bug的根源,我们可以尝试让每次生成TchForm对象时就更新数据:
方法一
1. 利用 __init__将数据库操作放入对象变量中
修改TchForm类
1
2
3
4
5
6
7
8
9
10
|
#教师表单验证规则 class TchForm(Form): name = fields.CharField(max_length = 16 , min_length = 2 , widget = widgets.TextInput(attrs = { 'class' : 'form-control' })) t2c = fields.MultipleChoiceField( # choices=models.Classes.objects.values_list('id', 'title'), widget = widgets.SelectMultiple(attrs = { 'class' : 'form-control' }) ) def __init__( self , * args, * * kwargs): # 自定义__init__ super (TchForm, self ).__init__( * args, * * kwargs) # 调用父类的__init__ self .fields[ 't2c' ].choices = models.Classes.objects.values_list( 'id' , 'title' ) # 为字段t2c的choices赋值 |
2. 验证
在班级表中新增一条记录
再在教师表中添加
方法二
1. 利用django.forms.models模块中的queryset连接数据库
修改TchForm类
1
2
3
4
5
6
7
8
9
10
|
#教师表单验证规则 from django.forms import models as form_models # 导入django.forms.models class TchForm(Form): name = fields.CharField(max_length = 16 , min_length = 2 , widget = widgets.TextInput(attrs = { 'class' : 'form-control' })) #重新定义字段 t2c = form_models.ModelMultipleChoiceField( # choices=models.Classes.objects.values_list('id', 'title'), queryset = models.Classes.objects. all (), # 利用queryset连接数据库,只能连接object类型 widget = widgets.SelectMultiple(attrs = { 'class' : 'form-control' }) ) |
2. 验证
由于TchForm类中,queryset只能连接object类型,所以,需要设置models.py中的Classes类的返回值。
设置models.py中的Classes类的返回值
1
2
3
4
|
class Classes(models.Model): title = models.CharField(max_length = 32 ) def __str__( self ): return self .title |
在班级表中新增一条记录
再在教师表中添加
以上所述是小编给大家介绍的使用Django Form解决表单数据无法动态刷新的两种方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/OldJack/p/7121510.html