Как динамически задавать урлы в Django
У меня есть форма, которая обновляет количество товара или пользовательского заказа, в настоящее время я использую
"{% if custom_orders %}{% url 'custom_order_update' item.custom_order.id %}{% else %}{% url 'update_bag' item.product_id %}{% endif %}"
в качестве URL действия, однако Django выдает ошибку перенаправления для этого синтаксиса. Может ли кто-нибудь порекомендовать другой способ динамической установки URL?
urls.py - пакетное приложение
from django.urls import path
from . import views
urlpatterns = [
path('', views.view_bag, name='view_bag'),
path('add/<product_id>/', views.add_to_bag, name='add_to_bag'),
path('update/<product_id>/', views.update_bag, name='update_bag'),
path('remove/<product_id>/', views.remove_from_bag, name='remove_from_bag'),
]
views.py - пакетное приложение
from django.shortcuts import render, redirect, reverse
def view_bag(request):
"""
A view to return bag page
"""
bag = request.session.get('bag', {})
custom_orders = bag.get('custom_orders', [])
context = {
'custom_orders': custom_orders
}
return render(request, 'bag/bag.html', context)
def add_to_bag(request, product_id):
""" Add a quantity of the specified product to the shopping bag """
quantity = int(request.POST.get('quantity'))
redirect_url = request.POST.get('redirect_url')
bag = request.session.get('bag', {})
if product_id in list(bag.keys()):
bag[product_id] += quantity
else:
bag[product_id] = quantity
request.session['bag'] = bag
return redirect(redirect_url)
def update_bag(request, product_id):
bag = request.session.get('bag', {})
quantity = int(request.POST.get('quantity'))
print(quantity)
if quantity > 0:
bag[product_id] = quantity
else:
bag.pop(product_id, None)
request.session['bag'] = bag
return redirect(reverse('view_bag'))
def remove_from_bag(request, product_id):
bag = request.session.get('bag', {})
bag.pop(product_id)
request.session['bag'] = bag
return redirect(reverse('view_bag'))
urls.py custom_order app
from django.urls import path
from . import views
urlpatterns = [
path('', views.custom_order, name='custom_order'),
path('price/<int:custom_order_id>/', views.custom_order_details, name='price'),
path('add_custom_order/<int:custom_order_id>/', views.add_custom_order_to_bag, name='add_custom_order'),
path('update_custom_order/<int:custom_order_id>/', views.custom_order_update, name='custom_order_update'),
path('delete_custom_order/<int:custom_order_id>/', views.custom_order_delete, name='custom_order_delete'),
]
views.py custom_order app
Рассмотрите возможность использования пространств имен URL [django-docs] впредь, чтобы даже если разные приложения используют одинаковые имена URL, они могли быть разрешены.
Теперь мы добавим имя приложения во все файлы URLConfig нашего приложения, чтобы мы могли использовать пространства имен URL. Например, в bag_app.urls
.
from django.urls import path
from . import views
app_name = "bag_app"
urlpatterns = [
# ••• Same as before •••
]
Затем include
мы поместим модули URLConfig из различных приложений в корневой модуль URLConfig.
from django.urls import include, path
urlpatterns = [
path("root-url-for-bag_app", include("bag_app.urls"))
# ••• Include the rest here •••
]
Теперь код в шаблоне должен использовать пространства имен URL следующим образом:
{% if custom_orders %}
{% url 'custom_order_app:custom_order_update' item.custom_order.id %} # [1]
{% else %}
{% url 'bag_app:update_bag' item.product_id %}
{% endif %}
[1] Как мы делали в bag_app
, вы должны добавить имя приложения в URLConfig custom_order_app
и include
это в корневой модуль URLConfig.