Как динамически задавать урлы в 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.

Вернуться на верх