使用 django 和 jquery 创建依赖下拉菜单时遇到问题
Posted
技术标签:
【中文标题】使用 django 和 jquery 创建依赖下拉菜单时遇到问题【英文标题】:Having problems creating dependent drop downs using django and jquery 【发布时间】:2012-12-18 12:09:55 【问题描述】:所以我找到了this 关于如何制作两个依赖下拉菜单的信息。我按照示例进行操作,现在当我尝试使用下拉菜单加载页面时,出现以下错误:
AttributeError at /brewkeep/beers/
'dict' object has no attribute 'status_code'
这是回溯:
Environment:
Request Method: GET
Request URL: http://192.168.1.111:8080/brewkeep/beers/
Django Version: 1.4
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'brewkeep',
'django.contrib.admin')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "/home/di/djangostack-1.4-1/apps/django/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
188. response = middleware_method(request, response)
File "/home/di/djangostack-1.4-1/apps/django/lib/python2.7/site-packages/django/middleware/common.py" in process_response
94. if response.status_code == 404:
Exception Type: AttributeError at /brewkeep/beers/
Exception Value: 'dict' object has no attribute 'status_code'
这是我的代码:
urls.py
(r'^brewkeep/beers/$', 'brewkeep.templatetags.brewery_beer_select'),
(r'^brewkeep/beers/(?P<brewery_id>[-\w]+)/all_json_models/$', 'brewkeep.views.beer_views.show_beers'),
models.py
class Brewery(models.Model):
idbrewery = models.AutoField(primary_key=True)
name = models.CharField(max_length=765)
class Beer(models.Model):
idbeer = models.AutoField(primary_key=True)
brewery = models.ForeignKey(Brewery, null=True, on_delete=models.SET_NULL)
templatetags.py
from brewkeep.models import Brewery
from django import template
register = template.Library()
@register.inclusion_tag("show_beers.html")
def brewery_beer_select(request):
breweries = Brewery.objects.all().order_by('name')
return 'breweries' : breweries
show_beers.html
<form action="" method="get" accept-charset="utf-8">
<p>Brewery:</p>
<select name="brewery" id="brewery">
<option value="">Select a brewery</option>
% for brewery in breweries %
<option value="brewery.idbrewery">brewery.name</option>
% endfor %
</select>
<select name="beer" id="beer" disabled="true">
<option>Select a beer</option>
</select>
</form>
<script src=" STATIC_URL admin/js/jquery.min.js">
$(document).ready(
function()
$("select#brewery").change(function()
if ($(this).val() == '')
$("select#beer").html("<option>Select a beer</option>");
$("select#beer").attr('disabled', true);
else
var url = "/brewkeep/beers/" + $(this).val() + "/all_json_models";
var brewery = $(this).val();
$.getJSON(url, function(beers)
var options = '<option value="">Select a beer</option>';
for (var i = 0; i < beers.length; i++)
options += '<option value="' + beers[i].pk + '">' + beers[i].fields['description'] + '</option>';
$("select#beer").html(options);
$("select#beer option:first").attr('selected', 'selected');
$("select#beer").attr('disabled', false);
);
);
$("select#beer").change(function(vent)
if ($(this).val() == '')
return;
);
);
</script>
beer_views.py
def show_beers(request, brewery_id):
brewery_obj = Brewery.objects.get(idbrewery=brewery_id)
beers = Beer.objects.all().filter(brewery=brewery_obj).order_by('name')
json_models = serializers.serialize("json", beers)
return HttpResponse(json_models, mimetype="application/javascript")
知道我错过了什么吗?
谢谢!
【问题讨论】:
依赖下拉列表是什么意思?一个选择框,其值由另一个选择框中的输入确定? @NickBewley 是的。我有两个下拉菜单。当我选择一个下拉列表时,我希望另一个下拉列表自动填充某些内容。然后当我选择第二个下拉菜单时,我希望页面显示某些内容。 【参考方案1】:为了满足您的要求,我喜欢使用django-smart-selects。它包含 js 功能,可以使用名为 ChainedForeignKey 的模型字段链接您的模型。例如,如果您想要一个电话链接选择,用户可以在其中选择一种手机类型、品牌和型号(例如 Iphone 4 S 或三星 Galaxy 2),它看起来像这样:
models.py:
from smart_selects.db_fields import ChainedForeignKey
class Series(models.Model):
series = models.CharField(max_length=10)
class Model(models.Model):
model = models.CharField(max_length=20)
series = models.ForeignKey(Series)
class Make(models.Model):
make = models.CharField(max_length=20)
model = models.ForeignKey('Model')
class Phone(models.Model):
make = models.ForeignKey(Make)
model = ChainedForeignKey(Model, chained_field='make', chained_model_field='make',)
series = ChainedForeignKey(Series, chained_field='model', chained_model_field='model',)
class PhoneForm(ModelForm):
class Meta:
model=Phone
模板.html:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
% block content %
<form action='' method='post' enctype='multipart/form-data'>
form.as_p
% csrf_token %
<input type='submit' value='submit' />
</form>
% endblock %
编辑:基于评论
来自文档
链接字段是同一模型上的字段,该字段也应链接。 链式模型字段是链式模型的字段,对应于链式字段也链接的模型。
更改为chained_model_field='name'
。
【讨论】:
所以我尝试使用django-smart-selects
。在我的模型中,我将Beer
模型中的Brewery
字段更改为:brewery = ChainedForeignKey(Brewery, chained_field="brewery", chained_model_field="brewery")
。在我这样做之后,当我转到我的表单时,Brewery
字段的下拉列表不会填充。
按照编辑中的描述更改链式模型字段,看看是否能解决您的问题。【参考方案2】:
为您的啤酒选择中的选项编写一个简单的模板beers_select_options.html
-
<option>Select a beer</option>
% for beer in beers %
<option value=" beer.idbeer "> beer </option>
% enfor %
为它提供一个视图
def ajax_get_beers(request):
idbrewery = int(request.POST['idbrewery'])
brewery = Brewery.objects.get(idbrewery=idbrewery)
beers = Beer.objects.filter(brewery=brewery)
return render_to_response('beers_select.html', 'beers': beers)
然后将函数附加到啤酒厂选择框上的更改事件 -
$('#brewery').change(function()
var idbrewery = $(this).find(':selected').val();
$.ajax(
type: 'POST',
url: '/your/ajax_get_beers/view',
data: 'idbrewery': idbrewery
success: function(options_html)
$('#beer').html(options_html);
);
);
这样就可以了,除了你可能有 csrf 保护,所以你需要在你的 javascript 之前添加以下内容(参见docs) -
function csrfSafeMethod(method)
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
var csrftoken = $.cookie('csrftoken');
$.ajaxSetup(
crossDomain: false,
cache: false,
beforeSend: function(xhr, settings)
if (!csrfSafeMethod(settings.type))
xhr.setRequestHeader("X-CSRFToken", csrftoken);
);
这需要jquery cookie plugin(有一个替代方法可以在django docs 中获取cookie)。
我还没有测试我的代码,但我认为这就是你真正需要的(我想你需要在你的 url conf 中添加一个 ajax 视图)。
【讨论】:
以上是关于使用 django 和 jquery 创建依赖下拉菜单时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章
根据 DJango/Ajax 中的第一个选定下拉菜单创建下拉选择
django & ajax 依赖的 html 选择列表(级联下拉列表)