title: How to Implement 3-way Dependent/Chained Dropdown List with Django?
body: <p>I am using django and postgresql. I'm dealing with a 3-way dependent drop-down list. After adding the country selection, the province area is automatically updated depending on the selected country. After selecting a province, the county field opens only when the page is refreshed. I would be glad if you help me in this regard.</p>
  
  <h1>models.py</h1>
  
  <pre><code>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
  </code></pre>
  
  <h1>forms.py</h1>
  
  <pre><code>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')
  </code></pre>
  
  <h1>views.py</h1>
  
  <pre><code>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})
  </code></pre>
  
  <h1>templates .html</h1>
  
  <pre><code>&lt;h2&gt;Person Form&lt;/h2&gt;
    &lt;form method="post" id="personForm" data-cities-url="{% url 'ajax_load_cities' %}" novalidate&gt;
      {% csrf_token %}
      &lt;table&gt;
        {{ form.as_table }}
      &lt;/table&gt;
      &lt;button type="submit"&gt;Save&lt;/button&gt;
      &lt;a href="{% url 'person_changelist' %}"&gt;Nevermind&lt;/a&gt;
    &lt;/form&gt;
    &lt;script src="https://code.jquery.com/jquery-3.3.1.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      $("#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);
          }
        });
      });
    &lt;/script&gt;
  </code></pre>
  
  <p>I'm referring to the example here.</p>
  
  <p><a href="https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html" rel="noreferrer">https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html</a></p>