How can I make chained multiple choice fields in Django with JQuery?

我们两清 提交于 2021-01-29 16:27:17

问题


I want to make a chained multiple choice field. I have working code for chained dropdown boxes below. I want to be able to choose more than one option at each level and have the next level return all records for each of the selected values. How can I make this happen? (my code is not very DRY, so appreciate any notes on that as well, but that is secondary)

models.py

        class Nace_Level_1(models.Model):
            code = models.CharField(max_length=1)
            name = models.CharField(max_length=200)
            short_name = models.CharField(max_length=100)
            notes = models.TextField()

            def __str__(self):
                return self.short_name

        class Nace_Level_2(models.Model):
            parent = models.ForeignKey(Nace_Level_1, on_delete=models.CASCADE)
            code = models.CharField(max_length=2)
            name = models.CharField(max_length=200)
            short_name = models.CharField(max_length=100)
            notes = models.TextField()

            def __str__(self):
                return self.short_name

        class Nace_Level_3(models.Model):
            parent = models.ForeignKey(Nace_Level_2, on_delete=models.CASCADE)
            code = models.CharField(max_length=4)
            name = models.CharField(max_length=200)
            short_name = models.CharField(max_length=100)
            notes = models.TextField()

            def __str__(self):
                return self.short_name

        class Nace_Level_4(models.Model):
            parent = models.ForeignKey(Nace_Level_3, on_delete=models.CASCADE)
            code = models.CharField(max_length=5)
            name = models.CharField(max_length=200)
            short_name = models.CharField(max_length=100)
            notes = models.TextField()

            def __str__(self):
                return self.short_name

        class Nace_Level_5(models.Model):
            parent = models.ForeignKey(Nace_Level_4, on_delete=models.CASCADE, blank=True, null=True)
            level_3 = models.ForeignKey(Nace_Level_3, on_delete=models.CASCADE, blank=True, null=True)
            level_2 = models.ForeignKey(Nace_Level_2, on_delete=models.CASCADE, blank=True, null=True)
            level_1 = models.ForeignKey(Nace_Level_1, on_delete=models.CASCADE, blank=True, null=True)
            code = models.CharField(max_length=6)
            name = models.CharField(max_length=200)
            short_name = models.CharField(max_length=100)
            notes = models.TextField()

            def __str__(self):
                return self.short_name

forms.py

        class NaceForm(forms.ModelForm):
            level_5 = forms.ChoiceField(label='', choices=Nace_Level_5.objects.none())

            class Meta:
                model = Nace_Level_5
                fields = ('level_1','level_2','level_3','parent','level_5')
                labels = {'level_1': (""),
                          'level_2': (""),
                          'level_3': (""),
                          'parent' : (""),}

            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self.fields['level_1'].queryset = Nace_Level_1.objects.all()
                self.fields['level_2'].queryset = Nace_Level_2.objects.none()
                self.fields['level_3'].queryset = Nace_Level_3.objects.none()
                self.fields['parent'].queryset = Nace_Level_4.objects.none()
                self.fields['level_1'].widget.attrs={'data-nace-url':'/ajax/load-level-2/'}
                self.fields['level_2'].widget.attrs={'data-nace-url':'/ajax/load-level-3/'}
                self.fields['level_3'].widget.attrs={'data-nace-url':'/ajax/load-level-4/'}
                self.fields['parent'].widget.attrs={'data-nace-url':'/ajax/load-level-5/'}

urls.py


        urlpatterns = [
            path("industries/", views.NaceCreateView.as_view(), name="industries"),

            path('ajax/load-level-2/', views.load_level_2, name="ajax_load_level_2"),
            path('ajax/load-level-3/', views.load_level_3, name="ajax_load_level_3"),
            path('ajax/load-level-4/', views.load_level_4, name="ajax_load_level_4"),
            path('ajax/load-level-5/', views.load_level_5, name="ajax_load_level_5"),
        ]

views.py


        class NaceCreateView(CreateView):
            template_name = 'main/industries.html'
            model = Nace_Level_5
            form_class = NaceForm


        def load_level_2(request):
            level_1_id = request.GET.get('level_1')
            level_2 = Nace_Level_2.objects.filter(parent=level_1_id)
            return render(request, 'main/level_dropdown.html', {'levels': level_2})

        def load_level_3(request):
            level_2_id = request.GET.get('level_2')
            level_3 = Nace_Level_3.objects.filter(parent=level_2_id)
            return render(request, 'main/level_dropdown.html', {'levels': level_3})

        def load_level_4(request):
            level_3_id = request.GET.get('level_3')
            level_4 = Nace_Level_4.objects.filter(parent=level_3_id)
            return render(request, 'main/level_dropdown.html', {'levels': level_4})

        def load_level_5(request):
            level_4_id = request.GET.get('parent')
            level_5 = Nace_Level_5.objects.filter(parent=level_4_id)
            return render(request, 'main/level_dropdown.html', {'levels': level_5})

templates/main/industries.html

        <div class='row'>
            <div class='col'>
                <form method="post" id="naceForm" novalidate>
                    {% csrf_token %}
                    <table>
                        {{ form.as_table }}
                    </table>
                </form>
            </div>
        </div>

        <script>
            $("#id_level_1").change(function () {
                var url = $("#id_level_1").attr("data-nace-url");
                var level_1_id = $(this).val();
                $.ajax({
                    url: url,
                    data: {
                    'level_1': level_1_id       
                    },
                    success: function (data) {
                    $("#id_level_2").html(data);
                    }
                });

            });
            $("#id_level_2").change(function () {
                var url = $("#id_level_2").attr("data-nace-url");
                var level_2_id = $(this).val();
                $.ajax({
                    url: url,
                    data: {
                    'level_2': level_2_id       
                    },
                    success: function (data) {
                    $("#id_level_3").html(data);
                    }
                });

            });
            $("#id_level_3").change(function () {
                var url = $("#id_level_3").attr("data-nace-url");
                var level_3_id = $(this).val();
                $.ajax({
                    url: url,
                    data: {
                    'level_3': level_3_id       
                    },
                    success: function (data) {
                    $("#id_parent").html(data);
                    }
                });

            });
            $("#id_parent").change(function () {
                var url = $("#id_parent").attr("data-nace-url");
                var parent_id = $(this).val();
                $.ajax({
                    url: url,
                    data: {
                    'parent': parent_id       
                    },
                    success: function (data) {
                    $("#id_level_5").html(data);
                    }
                });

            });
          </script>

templates/main/level_dropdown.html

        <option value="">---------</option>
        {% for level in levels %}
        <option value="{{ level.id }}">{{ level.short_name }}</option>
        {% endfor %}

来源:https://stackoverflow.com/questions/61373313/how-can-i-make-chained-multiple-choice-fields-in-django-with-jquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!