在Django里面,看看如何通过form来实现一个动态地select下拉框的效果。
首先看看静态的select的效果
models.py
1
2
3
4
5
|
class
city(models.Model):
name
=
models.CharField(max_length
=
32
)
#确保admin里面显示的是名字而不是object
def
__str__(
self
):
return
self
.name
|
admin.py
1
2
3
|
from
django.contrib
import
admin
from
app01.models
import
city
admin.site.register(city)
|
然后在admin里面随便添加几条数据
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
######################## Form #####################
from
django
import
forms
from
django.forms
import
widgets
from
django.forms
import
fields
from
app01
import
models
from
django.forms
import
ModelChoiceField
class
FM(forms.Form):
#这里使用value_list是因为传递给choices的格式刚好是一个列表包括的元组格式
city3
=
fields.ChoiceField(
choices
=
models.city.objects.
all
().values_list(
'id'
,
'name'
),
widget
=
widgets.Select
)
def
fm(request):
if
request.method
=
=
"GET"
:
obj
=
FM()
return
render(request,
'fm.html'
,{
'obj'
: obj})
|
效果如下
这个时候,如果我在后台对city这个表进行了修改,刷新我的页面,显示的效果是不会改变的!只有当我重启整个Django,对应的数据才会在前台进行改变。
这是为什么呢?很简单,看看我们在class FM里面的定义,city3是这个类的静态字段,换句话说,这个字段在编译这个类的时候就初始化了,而当我们刷新页面,实例化对象的时候,这个静态字段的值并不会因为实例的不同而改变。那么为了改变对应的字段,解决方案就很明显了,要么在实例化以后的对象重新赋值,要么在实例化的过程中复制。这里我选择在实例化的过程中赋值,只需要自己重写一下init构造函数就行了。
修改代码:
注意super的使用,继承父类的init方法,然后再执行自己的赋值语句
1
2
3
4
5
6
7
8
|
city3
=
fields.ChoiceField(
#反正要重新赋值,静态字段就没有必要赋值了
choices
=
[]
)
def
__init__(
self
,
*
args,
*
*
kwargs):
super
(FM,
self
).__init__(
*
args,
*
*
kwargs)
self
.fields[
'city3'
].choices
=
models.city.objects.
all
().values_list(
'id'
,
'name'
)
|
这样就实现了动态地改变select内容的效果。
除此以外,Django本身也提供了一个内置的类来实现这个动态效果。
导入类,然后定义一个字段
1
2
3
4
5
|
from
django.forms
import
ModelChoiceField
city4
=
forms.ModelChoiceField(
queryset
=
models.city.objects.
all
(),
empty_label
=
'请选择城市'
,
)
|
效果如下
本文转自 beanxyz 51CTO博客,原文链接:http://blog.51cto.com/beanxyz/1969418,如需转载请自行联系原作者