Django管理表单 - 如何动态改变选择值
我有这种情况: 我有模型项目,地区和国家。Django管理表单 - 如何动态改变选择值
class Item(models.Model):
name = models.CharField(max_length=255)
alias = models.SlugField(unique=True)
country = models.OneToOneField(Country, default=0)
region = models.OneToOneField(Region, default=0, related_name='')
class Region(models.Model):
name = models.CharField(max_length=100)
country = models.ForeignKey(Country, default=0)
class Country(models.Model):
name = models.CharField(max_length=100)
当我在管理方面增加一个项目,我选择的国家我想自动建立本地区与Regions
只从选定Country
选择。
我知道如何在JavaScript中做到这一点,但我不知道它是如何正确的在Django中做到这一点。
你需要重写你的管理形式的清洁方法:
def clean(self):
super(CustomItemForm, self).clean() #if necessary
if 'region' in self._errors:
"""
reset the value (something like this i
think to set the value b/c it doesnt get set
b/c the field fails validation initially)
"""
region = Region.objects.get(pk=self.data['region'])
self.initial['region'] = region.id
self.cleaned_data['region'] = region
self.region = region
# remove the error
del self._errors['region']
return self.cleaned_data
谢谢,你是伟大的人。 我试图让def clear_region,但我做错了方式。 而在你的清洁需要添加行 返回self.cleaned_data – yAnTar 2012-04-05 14:01:22
好赶上,我编辑我的答案(这是从我的项目坏的复制粘贴) – 2012-04-05 14:06:30
Soory为我的延迟(我有其他任务)。
我解决了这个问题不建议库(与简单的JavaScript),但存在一个问题:当我改变国家 - 选择区域自动改变,但我不能保存新的区域值(当来自同一国家的另一个区域 - 没有问题),因为错误选择一个有效的选择。该选择不是可用选择之一。
模型是在第一个问题是相同的,但对模范国家等于默认值1
我的第一个办法是改变国家通过formfield_key功能选择,
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'region':
kwargs["queryset"] = Region.objects.filter(country=self.country)
return db_field.formfield(**kwargs)
,但我不知道是保存对象,还是编辑对象。
Here写道 - 最好的办法是通过形式 变化,现在我有代码:
class Item(models.Model):
country = models.ForeignKey(Country, default=1)
region = models.ForeignKey(Region, related_name='')
class ItemAdmin(admin.ModelAdmin):
form = CustomItemForm
prepopulated_fields = {"alias": ("name",)}
list_filter = ('country', 'category',)
class CustomItemForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
try:
country = kwargs['instance'].country
except KeyError:
country = 1
super(CustomItemForm, self).__init__(*args, **kwargs)
self.fields['region'].queryset = Region.objects.filter(country=country)
我刚刚在我的一个应用程序昨天解决了这个问题,在我的'__init__'方法中,如果'kwargs ['instance']'没有设置并且抛出异常'country = 1',我的回答也会在 – 2012-04-05 13:41:53
的下方抛出'Region.objects.fitler(country = country)'代码行中的错误b/c过滤器期望对象实例不是int。只是FYI可能会失败 – 2012-04-05 13:52:20
如果”在django接受你选择的值时遇到麻烦,因为它不认为它应该在那里出现,让查询集引用每个可能的值,但是然后用空集覆盖“选择”属性。后一部分将避免django构造一个巨大的选项列表,这个选项列表正好被动态javascript覆盖。
我知道这不是管理员屏幕可以使用的功能,但是我在为非管理员做类似的事情时发现了这个页面,所以我想我也会在这里回答它。下面是我使用的是什么:
from django.shortcuts import render_to_response
from django import forms
from django.template import RequestContext
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.core import serializers
# other imports
class AddRouteForm (forms.Form):
router = forms.ModelChoiceField (queryset=Router.objects.all())
peer = forms.ModelChoiceField (queryset=Peer.objects.all())
peer.choices = []
# other stuff not relevant
def get_peers (request):
router_id = request.GET['router_id']
router = Router.objects.get(id=router_id)
data = serializers.serialize ("json", router.peer_set.filter(transit_capable=True))
return HttpResponse (data, content_type="text/json")
def add_route (request):
if request.method == "POST":
form = AddRouteForm (request.POST)
if form.is_valid():
# TODO something here
return HttpResponseRedirect (reverse ("staticroute.views.index"))
else:
form = AddRouteForm()
return render_to_response ("staticroute/add_route.html", locals(), RequestContext(request))
在HTML文件(jQuery的需要太装):
<form method="POST">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Add Route" />
</form>
<script>
$("#id_router").change (function() {
var router_id = $('#id_router').val();
var items = [];
items.push ('<option value="" selected="selected">---------</option>');
$("#id_peer").html (items.join(''));
if (router_id != "") {
$.getJSON ('{% url staticroute.views.get_peers %}', {router_id:router_id}, function(data) {
$.each (data, function (index, val) {
items.push ('<option value="' + val.pk + '">' + val.fields.description + ' (' + val.fields.address + ')</option>');
});
$("#id_peer").html (items.join(''));
});
}
}).change();
</script>
您将需要使用Ajax做
在views.py这个:当第一次选择变化(国家)的值时,为该国家的所有地区做一个ajax请求并用这些值过滤第二次选择。 – 2012-03-29 10:38:54
我知道,但我还有一个问题 - 它如何在Django上做对。 我可以在管理区的模板中插入javascript代码并生成另一个选择。 $( '#选择1')。改变(函数(){$ ,AJAX({ }) }) – yAnTar 2012-03-29 12:05:17
有一些Django的包,比如http://code.google.com/p/django-ajax -filtered-fields /和https:// github。com/twidi/django-ajax-select你可以试试这些 – Pannu 2012-03-29 14:59:53