Это легко, не волнуйся. Но вы должны использовать базовый Ajax-запрос для этого, чтобы вы узнали что-то новое, будьте счастливы!
Во-первых, когда пользователь еще не выбрал какую-либо страну, мы должны скрыть все города в форме или когда пользовательвыберите неопределенную страну (возможно, у вас нет информации о городе в таблице стран), мы должны обработать все ошибки. Поэтому добавьте следующие строки в модель формы:
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 load_cities(request):
country_id = request.GET.get('country')
cities = City.objects.filter(country_id=country_id).order_by('name')
return render(request, 'city_dropdown_list_options.html', {'cities': cities})
Эта маленькая функция будет запрашивать поле 'страна' в вашей форме и отправлять города с фильтрами. Давайте создадим новый html-файл в вашем каталоге, например 'city_dropdown_list_options.html':
<option value="">---------</option>
{% for city in cities %}
<option value="{{ city.pk }}">{{ city.name }}</option>
{% endfor %}
Добавьте новый URL-адрес в ваш urls.py:
path('ajax/load-cities/', views.load_cities, name='ajax_load_cities')
Теперь пришло время создать запрос AJAXв твоей форме. В приведенном ниже примере я использую jQuery, но вы можете использовать любой каркас JavaScript (или просто обычный JavaScript) для создания асинхронного запроса:
{% block content %}
<h2>Your Form</h2>
<form method="post" id="ProfileUpdateForm" data-cities-url="{% url 'ajax_load_cities' %}" novalidate>
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Save</button>
<a href="{% url 'whatyouwant' %}">Go!</a>
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$("#id_country").change(function () {
var url = $("#ProfileUpdateForm").attr("data-cities-url"); // get the url of the `load_cities` view
var countryId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/ajax/load-cities/)
data: {
'country': countryId // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
$("#id_city").html(data); // replace the contents of the city input with the data that came from the server
}
});
});
</script>
{% endblock %}
Та да! Если вы выберете страну, вы увидите только города, которые отфильтрованы по стране. Это волшебство, верно? Все это я узнал из https://www.simpleisbetterthancomplex.com,, который вы можете искать по следующему названию: «Как реализовать зависимый / цепной выпадающий список с помощью Django?». Удачи, братан!