Django: динамическое обновление списка в форме
Проблема с отображением списка в форме при выборе города: JavaScript и AJAX не обновляют содержимое. Как исправить?
Есть функция по оформлению заказа (create_order), которая обрабатывает форму. В форме есть поле (country) - город. Задумка такая, хочу чтобы пользователь выбирал свой город и видел отделения Новой Почты в своем городе.
Есть две функции которые обрабатывают город и выводят эти отделения, но в Django они не работают. Подскажите, как это сделать.
views.py:
def create_order(request):
warehouses = []
if request.method == "POST":
form = CreateOrderForm(data=request.POST)
if form.is_valid():
try:
with transaction.atomic():
if request.user.is_authenticated:
user = request.user
cart_items = Cart.objects.filter(user=user)
else:
session_key = request.session.session_key
cart_items = Cart.objects.filter(session_key=session_key)
if cart_items.exists():
# Создать заказ
if request.user.is_authenticated:
order = Order.objects.create(
user=user,
phone_number=form.cleaned_data["phone_number"],
country=form.cleaned_data["country"],
delivery_method=form.cleaned_data["delivery_method"],
delivery_address=form.cleaned_data["delivery_address"],
comment=form.cleaned_data["comment"],
)
else:
order = Order.objects.create(
session_key=request.session.session_key,
phone_number=form.cleaned_data["phone_number"],
country=form.cleaned_data["country"],
delivery_method=form.cleaned_data["delivery_method"],
delivery_address=form.cleaned_data["delivery_address"],
comment=form.cleaned_data["comment"],
)
# Создать заказанные товары
for cart_item in cart_items:
product = cart_item.product
title = cart_item.product.title
price = cart_item.product.price
amount = cart_item.amount
OrderItem.objects.create(
order=order,
product=product,
title=title,
price=price,
amount=amount,
)
# Очищение корзины пользователя
cart_items.delete()
# Получение и отправка отделений в форме JsonResponse
country = form.cleaned_data["country"]
country_ref = get_city_ref(country)
warehouses = get_warehouses(country_ref)
except ValidationError as e:
messages.warning(request, str(e))
return redirect("product:index")
else:
if request.user.is_authenticated:
initial = {
"email": request.user.email,
"first_name": request.user.first_name,
"last_name": request.user.last_name,
"middle_name": request.user.middle_name,
}
form = CreateOrderForm(initial=initial)
else:
form = CreateOrderForm()
context = {"form": form, "warehouses": warehouses}
return render(request, "orders/create_order.html", context)
forms.py:
class CreateOrderForm(forms.Form):
email = forms.EmailField()
first_name = forms.CharField()
middle_name = forms.CharField()
last_name = forms.CharField()
phone_number = forms.CharField()
country = forms.CharField()
delivery_method = forms.CharField()
delivery_address = forms.CharField()
payment_on_get = forms.CharField()
comment = forms.CharField(required=False)
utils.py:
def get_city_ref(country):
"""Получает Ref определенного города."""
country_ref = ""
json = {
"apiKey": "",
"modelName": "Address",
"calledMethod": "getCities",
"methodProperties": {
"FindByString": country, # Передаем значение из формы
},
}
response = requests.post(
"https://api.novaposhta.ua/v2.0/json/", json=json, timeout=1
)
if response.status_code == 200:
data = response.json()["data"]
for country_item in data:
if country_item["Description"] == country:
country_ref = country_item["Ref"]
return country_ref
else:
print("Ошибка при получении country_ref:", response.text)
def get_warehouses(country_ref):
"""Получаем отделения из опеределенного города используя Ref."""
warehouses = []
# Получение отделений
json_data = {
"apiKey": "b0b6ea3934d1d018b3155eb1658c2e36",
"modelName": "AddressGeneral",
"calledMethod": "getWarehouses",
"methodProperties": {
"CityRef": country_ref, # Город
},
}
response = requests.post(
"https://api.novaposhta.ua/v2.0/json/", json=json_data, timeout=1
)
if response.status_code == 200:
data = response.json()["data"]
for item in data:
if item["Description"].split()[0] != "Поштомат":
warehouses.append(item["Description"])
return JsonResponse({"warehouses": warehouses})
create_order.html
<form action="{% url 'orders:create_order' %}" method="post">
{% csrf_token %}
<div class="row g-3">
<div class="col-12">
<label for="id_email" class="form-label">E-mail <span class="text-danger">*</span></label>
<input type="email" class="form-control" name="email" id="id_email" value="{% if form.email.value %}{{ form.email.value }}{% endif %}" placeholder="you@example.com" />
{% if form.email.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.email.errors }}</div>
{% endif %}
<hr />
</div>
<h4 class="text-uppercase fw-semibold mb-1">АДРЕСА ДЛЯ ВИСТАВЛЕННЯ РАХУНКУ</h4>
<div class="col-sm-4">
<label for="id_first_name" class="form-label">Ім'я <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="first_name" id="id_first_name" value="{% if form.first_name.value %}{{ form.first_name.value }}{% endif %}" />
{% if form.first_name.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.first_name.errors }}</div>
{% endif %}
</div>
<div class="col-sm-4">
<label for="id_last_name" class="form-label">Прізвище <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="last_name" id="id_last_name" value="{% if form.last_name.value %}{{ form.last_name.value }}{% endif %}" />
{% if form.last_name.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.last_name.errors }}</div>
{% endif %}
</div>
<div class="col-sm-4">
<label for="id_middle_name" class="form-label">По батькові <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="middle_name" id="id_middle_name" value="{% if form.middle_name.value %}{{ form.middle_name.value }}{% endif %}" />
{% if form.middle_name.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.middle_name.errors }}</div>
{% endif %}
</div>
<div class="col-12">
<label for="id_phone_number" class="form-label">Номер телефона <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="phone_number" id="id_phone_number" value="{% if form.phone_number.value %}{{ form.phone_number.value }}{% endif %}" placeholder="У форматі XXX XXX XXX XXX" />
{% if form.phone_number.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.phone_number.errors }}</div>
{% endif %}
</div>
<div class="col-12">
<label for="id_country" class="form-label">Ваш населений пункт <span class="text-danger">*</span></label>
<select class="form-select" name="country" id="id_country">
<option>Вибіріть ваш населений пункт</option>
<option value="Вінниця" {% if form.country.value == "Вінниця" %}selected{% endif %}>Вінниця</option>
<option value="Дніпро" {% if form.country.value == "Дніпро" %}selected{% endif %}>Дніпро</option>
<option value="Житомир" {% if form.country.value == "Житомир" %}selected{% endif %}>Житомир</option>
<option value="Запоріжжя" {% if form.country.value == "Запоріжжя" %}selected{% endif %}>Запоріжжя</option>
<option value="Івано-Франківськ" {% if form.country.value == "Івано-Франківськ" %}selected{% endif %}>Івано-Франківськ</option>
<option value="Київ" {% if form.country.value == "Київ" %}selected{% endif %}>Київ</option>
<option value="Кропивницький" {% if form.country.value == "Кропивницький" %}selected{% endif %}>Кропивницький</option>
<option value="Луцьк" {% if form.country.value == "Луцьк" %}selected{% endif %}>Луцьк</option>
<option value="Львів" {% if form.country.value == "Львів" %}selected{% endif %}>Львів</option>
<option value="Миколаїв" {% if form.country.value == "Миколаїв" %}selected{% endif %}>Миколаїв</option>
<option value="Одеса" {% if form.country.value == "Одеса" %}selected{% endif %}>Одеса</option>
<option value="Полтава" {% if form.country.value == "Полтава" %}selected{% endif %}>Полтава</option>
<option value="Рівне" {% if form.country.value == "Рівне" %}selected{% endif %}>Рівне</option>
<option value="Суми" {% if form.country.value == "Суми" %}selected{% endif %}>Суми</option>
<option value="Тернопіль" {% if form.country.value == "Тернопіль" %}selected{% endif %}>Тернопіль</option>
<option value="Харків" {% if form.country.value == "Харків" %}selected{% endif %}>Харків</option>
<option value="Херсон" {% if form.country.value == "Херсон" %}selected{% endif %}>Херсон</option>
<option value="Хмельницький" {% if form.country.value == "Хмельницький" %}selected{% endif %}>Хмельницький</option>
<option value="Черкаси" {% if form.country.value == "Черкаси" %}selected{% endif %}>Черкаси</option>
<option value="Чернівці" {% if form.country.value == "Чернівці" %}selected{% endif %}>Чернівці</option>
<option value="Чернігів" {% if form.country.value == "Чернігів" %}selected{% endif %}>Чернігів</option>
</select>
{% if form.country.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.country.errors }}</div>
{% endif %}
</div>
<div class="col-md-12 d-flex flex-column">
<label for="id_delivery_method" class="form-label">Спосіб доставки <span class="text-danger">*</span></label>
<div class="form-check form-check-inline mb-3">
<input class="form-check-input" type="radio" name="delivery_method" id="id_delivery_method" value="0"
{% if form.delivery_method.value == '0' %}checked{% endif %}/>
<label class="form-check-label" for="id_delivery_method">Meest пошта відділення</label>
{% if form.delivery_method.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.delivery_method.errors }}</div>
{% endif %}
</div>
<div class="form-check form-check-inline mb-3">
<input class="form-check-input" type="radio" name="delivery_method" id="id_delivery_method" value="1"
{% if form.delivery_method.value == '1' %}checked{% endif %}/>
<label class="form-check-label" for="id_delivery_method">Нова почта відділення</label>
{% if form.delivery_method.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.delivery_method.errors }}</div>
{% endif %}
</div>
</div>
<div class="col-12">
<label for="id_delivery_address" class="form-label">Знайти відділення <span class="text-danger">*</span></label>
<select class="form-select" name="delivery_address" id="id_delivery_address">
<option>Знайти відділення</option>
{% for warehouse in warehouses %}
<option value="{{ warehouse }}">{{ warehouse }}</option>
{% endfor %}
</select>
{% if form.delivery_addres.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.delivery_addres.errors }}</div>
{% endif %}
</div>
<div class="col-12">
<label for="id_payment_on_get" class="form-label">Спосіб оплати <span class="text-danger">*</span></label>
<div class="">
<input class="form-check-input" type="radio" name="payment_on_get" id="id_payment_on_get" value="1" checked />
<label for="id_payment_on_get" class="form-label">При отриманні</label>
{% if form.payment_on_get.errors %}
<div class="alert alert-danger alert-dismissible fade show">{{ form.payment_on_get.errors }}</div>
{% endif %}
</div>
</div>
<div class="col-12">
<label for="id_comment" class="form-label">Коментар (необов'язково)</label>
<textarea type="text" class="form-control h-auto" name="comment" id="id_comment" value="{% if form.comment.value %}{{ form.comment.value }}{% endif %}" rows="3"></textarea>
</div>
</div>
<hr class="my-4" />
<button class="w-100 btn btn-main btn-lg mb-5" type="submit">Купити зараз</button>
</form>
Буду очень признателен. Спасибо!