我面临的问题是我设置了一个区和在这个区下的城市,并保存了它。它正确地保存到数据库。当我回到页面更改城市并保存时,城市在数据库中被设为空,地区也被设为空怎么解呢上下文:试图覆盖Django-adminchange_form
的SchoolProfileForm
和省,区,市,和病房的可靠下拉框。当试图改变之前已经保存的城市时,地区值被重置为零,城市值也被重置为零(与ward相同,城市也被重置)
Javascript函数:
function resetDistrict() {
let $ = django.jQuery;
let district_list = '<option value="" selected="">---------</option>'
$('#select2-id_district-container').html(district_list);
console.log(district_list)
}
function getDistrict(province_id) {
resetDistrict()
let $ = django.jQuery;
$.get('/school/district/' + province_id, function (resp){
let district_list = '<option value="" selected="">---------</option>'
$.each(resp.data, function(i, item){
district_list += '<option value="'+ item.id +'">'+ item.name +'</option>'
});
$('#id_district').html(district_list);
});
}
function getDistrictfromDb(province_id) {
let $ = django.jQuery;
$.get('/school/district/' + province_id, function (resp){
let district_list = '<option value="" selected="">---------</option>'
$.each(resp.data, function(i, item){
district_list += '<option value="'+ item.id +'">'+ item.name +'</option>'
});
$('#id_district').html(district_list);
});
}
function resetCity() {
let $ = django.jQuery;
let city_list = '<option value="" selected="">---------</option>'
$('#select2-id_city-container').html(city_list);
console.log(city_list)
}
function getCity(district_id) {
resetCity();
let $ = django.jQuery;
$.get('/school/city/' + district_id, function (resp){
let city_list = '<option value="" selected="">---------</option>'
$.each(resp.data, function(i, item){
city_list += '<option value="'+ item.id +'">'+ item.name +'</option>'
});
$('#id_city').html(city_list);
});
}
function getCityfromDb(district_id) {
let $ = django.jQuery;
$.get('/school/city/' + district_id, function (resp){
let city_list = '<option value="" selected="">---------</option>'
$.each(resp.data, function(i, item){
city_list += '<option value="'+ item.id +'">'+ item.name +'</option>'
});
$('#id_city').html(city_list);
});
}
function resetWard() {
let $ = django.jQuery;
let ward_list = '<option value="" selected="">---------</option>'
$('#select2-id_ward-container').html(ward_list);
console.log(ward_list)
}
function getWard(city_id) {
resetWard()
let $ = django.jQuery;
$.get('/school/ward/' + city_id, function (resp){
let ward_list = '<option value="" selected="">---------</option>'
$.each(resp.data, function(i, item){
ward_list += '<option value="'+ item.id +'">'+ item.name +'</option>'
});
$('#id_ward').html(ward_list);
});
}
function getWardfromDb(city_id) {
let $ = django.jQuery;
$.get('/school/ward/' + city_id, function (resp){
let ward_list = '<option value="" selected="">---------</option>'
$.each(resp.data, function(i, item){
ward_list += '<option value="'+ item.id +'">'+ item.name +'</option>'
});
$('#id_ward').html(ward_list);
});
}
和forms.py来覆盖django管理表单:
class SchoolProfileForm(forms.ModelForm):
class Meta:
model = SchoolProfile
fields = '__all__'
def __init__(self, *args, **kwargs):
super(SchoolProfileForm, self).__init__(*args, **kwargs)
# when there is instance key, select the default value
# Province always loaded for initial data,
# because Province is on the first level
try:
self.initial['province'] = kwargs['instance'].province.id
except:
pass
province_list = [('', '---------')] + [(i.id, i.name) for i in Province.objects.all()]
# District, City, and Ward are on the child level,
# it will be loaded when user click the parent level
try:
self.initial['district'] = kwargs['instance'].district.id
district_init_form = [(i.id, i.name) for i in District.objects.filter(
province=kwargs['instance'].province
)]
except:
district_init_form = [('', '---------')]
try:
self.initial['city'] = kwargs['instance'].city.id
city_init_form = [(i.id, i.name) for i in City.objects.filter(
district=kwargs['instance'].district
)]
except:
city_init_form = [('', '---------')]
try:
self.initial['ward'] = kwargs['instance'].ward.id
ward_init_form = [(i.id, i.name) for i in Ward.objects.filter(
city=kwargs['instance'].city
)]
except:
ward_init_form = [('', '---------')]
# Overriding the form, adding onchange attribute to call the ajax function
self.fields['province'].widget = forms.Select(
attrs={
'id': 'id_province',
'class': 'location-select',
'onchange': 'getDistrict(this.value);',
},
choices=province_list,
)
self.fields['district'].widget = forms.Select(
attrs={
'id': 'id_district',
'class': 'location-select',
'onchange': 'getCity(this.value);',
},
choices=district_init_form
)
self.fields['city'].widget = forms.Select(
attrs={
'id': 'id_city',
'class': 'location-select',
'onchange': 'getWard(this.value);',
},
choices=city_init_form
)
self.fields['ward'].widget = forms.Select(
attrs={
'id': 'id_ward',
'class': 'location-select',
},
choices=ward_init_form
)
self.fields['locale'].widget = forms.TextInput(
attrs={
'id': 'id_locale',
'width': '200px',
},
)
views.py
def province_list(request):
province = Province.objects.all()
return JsonResponse({'data':[{'id': p.id, 'name': p.name} for p in province ]})
def district_list(request, province_id):
district = District.objects.filter(province_id=province_id)
return JsonResponse({'data': [{'id': d.id, 'name': d.name} for d in district ]})
def city_list(request, district_id):
city = City.objects.filter(district_id=district_id)
return JsonResponse({'data': [{'id': c.id, 'name': c.name} for c in city]})
def ward_list(request, city_id):
ward = Ward.objects.filter(city_id=city_id)
return JsonResponse({'data': [{'id': w.id, 'name': w.name} for w in ward ]})
完全集成在我的git-hub存储库中,并在DjangoCon 2022 US上展示。https://youtu.be/5r1jNJzVHBU?t=1789
我使用了AtocompleteWidget而不是base select,并且使用了基于django的自动完成JS