如何使用 Django 实现三向依赖/链式下拉列表?

isa*_*lla 7 python django ajax dropdown

我正在使用 django 和 postgresql。我正在处理一个三向依赖下拉列表。添加国家选择后,省区将根据所选国家自动更新。选择一个省后,只有在刷新页面时才会打开县字段。如果你在这方面帮助我,我会很高兴。

模型.py

from 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 District(models.Model):
    city = models.ForeignKey(City, 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)
    country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
    city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)
    district = models.ForeignKey(District, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.name
Run Code Online (Sandbox Code Playgroud)

表格.py

from django import forms
from .models import Person, Country, City, District

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person
        fields = ('name', 'birthdate', 'country', 'city', 'district')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['city'].queryset = City.objects.none()

        if 'country' in self.data:
            try:
                country_id = int(self.data.get('country'))
                self.fields['city'].queryset = City.objects.filter(country_id=country_id).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty City queryset
        elif self.instance.pk:
            self.fields['city'].queryset = self.instance.country.city_set.order_by('name')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['district'].queryset = District.objects.none()

        if 'city' in self.data:
            try:
                city_id = int(self.data.get('city'))
                self.fields['district'].queryset = District.objects.filter(city_id=city_id).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty District queryset
        elif self.instance.pk:
            self.fields['district'].queryset = self.instance.city.district_set.order_by('name')
Run Code Online (Sandbox Code Playgroud)

视图.py

def load_cities(request):
    country_id = request.GET.get('country')
    cities = City.objects.filter(country_id=country_id).order_by('name')
    return render(request, 'neighbor/city_dropdown_list_options.html', {'cities': cities})

def load_districts(request):
    city_id = request.GET.get('city')
    districts = District.objects.filter(city_id=city_id).order_by('name')
    return render(request, 'neighbor/district_dropdown_list_options.html', {'districts': districts})
Run Code Online (Sandbox Code Playgroud)

模板.html

<h2>Person Form</h2>
  <form method="post" id="personForm" data-cities-url="{% url 'ajax_load_cities' %}" novalidate>
    {% csrf_token %}
    <table>
      {{ form.as_table }}
    </table>
    <button type="submit">Save</button>
    <a href="{% url 'person_changelist' %}">Nevermind</a>
  </form>
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script>
    $("#id_country").change(function () {
      var url = $("#personForm").attr("data-cities-url");
      var countryId = $(this).val();
      $.ajax({
        url: url,
        data: {
          'country': countryId
        },
        success: function (data) {
          $("#id_city").html(data);
        }
      });
    });
    $("#id_city").change(function () {
      var url = $("#personForm").attr("data-districts-url");
      var cityId = $(this).val();
      $.ajax({
        url: url,
        data: {
          'city': cityId
        },
        success: function (data) {
          $("#id_district").html(data);
        }
      });
    });
  </script>
Run Code Online (Sandbox Code Playgroud)

我指的是这里的例子。

https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html

MAS*_*MAN 4

  1. 在 templates.html 文件中,您调用相同的 URL,因此国家和城市字段的相同视图会发生变化。您需要创建一个新的 URL 来处理 load_district 视图中的请求。

    进行以下更改

    $("#id_city").change(function () {
      var url = $("#personForm").attr("data-districts-url");
      var cityId = $(this).val();
      $.ajax({
        url: '{% url 'ajax_load_districts' %}',
        data: {
          'city': cityId
        },
        success: function (data) {
          $("#id_district").html(data);
        }
      });
    });
    
    Run Code Online (Sandbox Code Playgroud)

  2. 您不需要两次修改 init() 方法,只需从 froms.py 中删除这两行即可。(第 22 和 23 行)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加新的 URL 来处理分区的 ajax 请求

    path('ajax/load-district/', views.load_districts, name='ajax_load_districts'),
    
    Run Code Online (Sandbox Code Playgroud)

你可以克隆这个例子,我使用了国家,城市,瓦努埃...... https://github.com/masbhanoman/django_3way_chained_dropdown_list