Я не могу загрузить частичный шаблон Django из аякс-вызова JQuery
Мне нужно отправить список из ajax вызова используя JQuery, и отправить ответ с Django {{ переменные }} внутри них, я пробовал все, но JQuery всегда загружает всю текущую страницу вместо загрузки html файла, который содержит частичный шаблон, который просто
<!-- city_dropdown_list_options.html -->
<option value="">----city list----</option>
{% for city in cities %}
<option value="{{ city.pk }}">{{ city.name }}</option>
{% endfor %}
Вот шаблон, в котором находится JQuery
person_form.html
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{# NOTE: templates must be defined into a folder having the same name than
the application, like here countries/person_list.html, because Django
automatically search from <template_folder_in_app_folder/app_name/template.html #}
{% block content %}
<h2>{% trans "Person Form" %}</h2>
<form method="post" novalidate>
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Save</button>
<a href="{% url 'person_changelist' %}">Nevermind</a>
</form>
<div id="test"></div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
{# <script src="{% static 'js/test.js' %}"></script> #}
<script>
$("#id_country").change(function (){
// getting the url of the load_cities view
var url = $("#personForm").attr("data-cities-url");
// get the selected country id from the html element
var countryId = $(this).val();
$.ajax({
url: url,
data: {
// adding the countryId to GET parameters
'country': countryId
},
// data is the return value of the 'load_cities' function
success: function(data){
// replace the contents of the city input with the data
// that came from the server.
//console.log(data);
$("#id_city").html(data);
// $('#id_city').html(jQuery(data).find('#id_city').html());
}
});
});
</script>
{% endblock %}
Виды.py
from django.shortcuts import render
from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy
from .models import Person, City
from .forms import PersonForm
class PersonListView(ListView):
model = Person
context_object_name = 'people'
class PersonCreateView(CreateView):
model = Person
form_class = PersonForm
success_url = reverse_lazy('person_changelist')
class PersonUpdateView(UpdateView):
model = Person
form_class = PersonForm
success_url = reverse_lazy('person_changelist')
def load_cities(request):
country_id = request.GET.get('country')
cities = City.objects.filter(country_id=country_id).order_by('name')
return render(request, 'countries/city_dropdown_list_options.html', {'cities': cities})
Как я уже сказал, я получаю в качестве ответа всю форму person_form.html, в то время как я ожидаю в качестве ответа city_dropdown_list_options.html. Обратите внимание, что ответ не обязательно должен быть включенной частицей html, это также может быть простой вывод, сгенерированный представлением.
Я не очень хорошо разбираюсь в JQuery и, возможно, я что-то делаю не так или упускаю. Есть подсказки?
Я нашел решение
строка типа
path('load-cities/', views.load_cities, name='ajax_load_cities'),
отсутствовал в urls.py (на уровне приложения). Это означает, что не был определен маршрут для вызова аякс-вызова JQuery. Поэтому вызов был
http://127.0.0.1:8000/countries/add/?country=56
, который является тем же url, что и форма, и это не управлялось должным образом.
Я обнаружил, что лучшим решением для такой проблемы является создание специального маршрута для вызова ajax, как я это сделал, cal стал
http://127.0.0.1:8000/countries/add/load-cities/?country=56
Также это как будто не имело смысла вообще
var url = $("#personForm").attr("data-cities-url");
Я заменил его на прямое и ясное:
var url = "/countries/load-cities/";
И теперь все в порядке.
Мораль этой истории: Когда вы используете JQuery и делаете ajax вызовы внутри шаблона Django, никогда не забывайте определять специальный маршрут в urls.py. Помните, что вы используете фреймворк со встроенной системой маршрутизации. Эквиваленты PHP_SELF здесь больше не работают.
3 дня тяжелого труда, но я наконец-то справился. Я надеюсь, что этот ответ на мой вопрос поможет кому-то еще, кто столкнулся с той же проблемой.