一、无法动态更新数据的实例
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