javascript Django admin上的Django Chained Dropdown实现

sxissh06  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(84)

bounty已结束,回答此问题可获得+50声望奖励,奖励宽限期23小时后结束,Anee Mes希望引起更多关注此问题。

我面临的问题是我设置了一个地区和该地区下的城市并保存它。它正确地保存到数据库中。当我回到页面并更改城市并保存时,城市设置为null,数据库中的地区也设置为null我如何解决它上下文:试图覆盖Django-admin change_formSchoolProfileForm和省,区,市和区的可靠下拉列表。当试图改变之前已经保存的城市时,区值被重置为空,城市的值也被重置(与区相同的问题,城市也被重置)
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的admin表单:

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 ]})
gcuhipw9

gcuhipw91#

完全集成在我的git-hub存储库中,并在DjangoCon 2022 US上展示。https://youtu.be/5r1jNJzVHBU?t=1789
我使用AtocompleteWidget而不是base select,并修补了基于django的自动完成JS

相关问题