django下拉菜单html,怎么样在Django⾥实现联动下拉列表选
项?
从属或链接下拉列表是⼀个特殊字段,它依赖于先前选择的字段,以显⽰已过滤选项的列表。最常见的地⽅就是通过地址⾥选择省份,然后显⽰出该省份下所有城市列表。
以下⾯的应⽤程序为例:
models.pyfrom django.db import models
class Country(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class City(models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Person(models.Model):
name = models.CharField(max_length=100)
birthdate = models.DateField(null=True, blank=True)
html下拉菜单的制作方法country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
在应⽤程序中,我们将创建⼀个简单的表单处理来创建和更新⼈物对象。这个联动列表⽤来选择⼈物的国家和所在城市。
urls.pyfrom django.urls import include, path
from . import views
urlpatterns = [
path('', views.PersonListView.as_view(), name='person_changelist'),
path('add/', views.PersonCreateView.as_view(), name='person_add'),
path('/', views.PersonUpdateView.as_view(), name='person_change'),
]
创建三个视图函数:
views.pyfrom ic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy
from .models import Person
class PersonListView(ListView):
model = Person
context_object_name = 'people'
class PersonCreateView(CreateView):
model = Person
fields = ('name', 'birthdate', 'country', 'city')
success_url = reverse_lazy('person_changelist')
class PersonUpdateView(UpdateView):
model = Person
fields = ('name', 'birthdate', 'country', 'city')
success_url = reverse_lazy('person_changelist')
我们运⾏它,但是发现这个功能和我们想要要的不太⼀样,我们是想要根据选择国家,然后显⽰出该国家下的所有城市。但现在程序把所有国家的城市都给列出来了。
⽤⼀个简单的HTML代码把效果显⽰出来:{% extends 'base.html' %}
{% block content %}
Person Form
{% csrf_token %}
{{ form.as_table }}
Save
Nevermind
{% endblock %}
实现它的最佳⽅法是创建⼀个模型表单。通过这种⽅式,我们可以⾮常灵活地实现我们想要的功能。
forms.pyfrom django import forms
from .models import Person, City
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = ('name', 'birthdate', 'country', 'city')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['city'].queryset = ()
上⾯的⽰例有⼀个⽐较重要细的地⽅,我们简单的定义表单:现我们将覆盖默认的init⽅法,并将city字段的queryset设置为空的列表:
PS:不要忘记修改视图定义,使⽤我们的新表单类:views.pyclass PersonCreateView(CreateView):
model = Person
form_class = PersonForm
success_url = reverse_lazy('person_changelist')
class PersonUpdateView(UpdateView):
model = Person
form_class = PersonForm
success_url = reverse_lazy('person_changelist')
现在我们需要创建⼀个视图来返回给定国家/地区的城市列表。该视图将通过使⽤AJAX进⾏请求。
views.pydef load_cities(request):
country_id = ('country')
cities = City.objects.filter(country_id=country_id).order_by('name')
return render(request, 'hr/city_dropdown_list_options.html', {'cities': cities})
⽤这样简单的基于函数的视图就可以⾮常好的实现。下⾯是我们的HTML模板:
templates/hr/city_dropdown_list_options.html---------
{% for city in cities %}
{{ city.name }}
{% endfor %}
然后我们给之前的视图函数创建⼀个URL:
urls.pyfrom django.urls import include, path
from . import views
urlpatterns = [
path('', views.PersonListView.as_view(), name='person_changelist'),
path('add/', views.PersonCreateView.as_view(), name='person_add'),
path('/', views.PersonUpdateView.as_view(), name='person_change'),
path('ajax/load-cities/', views.load_cities, name='ajax_load_cities'), #
]
现在建⼀个AJAX请求。在下⾯的⽰例中,我使⽤的是jQuery,但可以使⽤任何JavaScript框架(或只是简单的JavaScript)来创建异步请求:
templates/person_form.html{% extends 'base.html' %}
{% block content %}
Person Form
{% csrf_token %}
{{ form.as_table }}
Save
Nevermind
$("#id_country").change(function () {
var url = $("#personForm").attr("data-cities-url"); // 获取 `load_cities` view
var countryId = $(this).val(); // 在HTML中获取选取的国家ID
$.ajax({ // 初始化 AJAX 请求
url: url, //设置请求地址(= localhost:8000/hr/ajax/load-cities/)
data: {
'country': countryId // countryId传到GET参数
},
success: function (data) { // 视图函数 `load_cities`返回到`data`
$("#id_city").html(data); // ⽤返回的数据替换城市输⼊框的内容
}
});
});
{% endblock %}
⾸先,我为表单(personForm)添加了⼀个ID,以便我们可以更容易地访问它。之后,我将数据属性添加到专⽤章data-cities-url。
然后,在此之后,我们在国家/地区下拉列表中有⼀个,设置id_country标识。此ID由Django⾃动⽣成。当它发⽣变化时,它会向服务器发出⼀个AJAX请求,并将所选的国家ID传递给我们的视图。
请求成功后,我们的脚本将在cities下拉列表中添加由load_cities视图呈现的HTML,由HTML ID id_city标识。
现在前端已经做好了,但是后端并没有按预期⼯作。如果我们现在提交表单,我们将看到以下错误消息:
那是因为我们在表单定义中列出了空的城市列表。这个错误消息是我特意向你显⽰的,因为它实际上⾮常有⽤。它将帮助我们保持形式的⼀致性。这意味着Django表单检查查询集中是否存在提供的值。
修改⼀下代码:
forms.pyfrom django import forms
from .models import Person, City
class PersonForm(forms.ModelForm):
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论