Omar Gonzales
Omar Gonzales

Reputation: 4008

Force URL to match a view with re_path

I've a view that should be called when entering:

1) stickersgallit.pe/ordenes/ingresos or
2) http://127.0.0.1:8000/ordenes/ingresos (locally).

However, it is entering and activating other view AddProduct, as it is guessing ordenes is c_slug and ingresos is product_slug, when they aren't:

path('<slug:c_slug>/<slug:product_slug>', views.AddProduct, name='AddProduct'),

Questions:

a) How to force /ordenes/ingresos to activate my classOrdersListView (in order/views/class OrdersListView(ListView))?
b) Or How can I limit what the URL views.AddProduct considers as c_slug and product_slug?

IMPORTANT:

In urls.py project level, order.urls is already on top of shop.urls but I keep getting:

ValueError at /ordenes/ingresos The view shop.views.AddProduct didn't return an HttpResponse object. It returned None instead.

urlpatterns = [
    path('admin/', admin.site.urls),
    path('ordenes/', include('order.urls')),
    path('', include('shop.urls')),
    path('carrito_de_compras/', include('cart.urls')),
    path('marketing/', include('marketing.urls')),
    path('registrarse/', views.signupView, name = 'signup'),
    path('ingresar/', views.signinView, name = 'signin'),
    path('salir/', views.signoutView, name = 'signout'),
    path('province/', views.get_province, name = 'province'),
]

Proyect urls.py:

from django.contrib import admin
from django.urls import path, include, re_path
from shop import views
from django.conf import settings
from django.conf.urls.static import static


urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('^/ordenes/', include('order.urls')),
    path('', include('shop.urls')),
    path('carrito_de_compras/', include('cart.urls')),
    path('marketing/', include('marketing.urls')),
    path('registrarse/', views.signupView, name = 'signup'),
    path('ingresar/', views.signinView, name = 'signin'),
    path('salir/', views.signoutView, name = 'signout'),
    path('province/', views.get_province, name = 'province')
]

shop URLs:

from django.contrib import admin
from django.urls import path, re_path

from . import views

app_name = 'shop'

urlpatterns = [
    path('admin', admin.site.urls),
    path('', views.allCat, name='allCat'),
    path('packs/', views.PacksPage, name='PacksPage'), #Todos los packs
    path('catalogo', views.CatalogoListView.as_view(), name='catalogo'), #Todos los productos unitarios
    path('muestras/', views.SamplePackPage, name='SamplePackPage'), #Todas las muestras
    path('province/', views.get_province, name='province'),
    path('district/', views.get_district, name='district'),
    path('quienes-somos/', views.quienes_somos, name='quienes_somos'),
    path('como-comprar/', views.como_comprar, name='como_comprar'),
    path('contactanos/', views.contactanos, name='contactanos'),
    path('preguntas-frecuentes/', views.preguntas_frecuentes, name='preguntas_frecuentes'),
    path('legales/privacidad', views.legales_privacidad, name='legales_privacidad'),
    path('legales/terminos', views.legales_terminos, name='legales_terminos'),
    path('muestras/<slug:sample_slug>/medida-y-cantidad', views.StepOneView_Sample.as_view(), name='SampleDetail'),
    path('muestras/<slug:sample_slug>/subir-arte', views.StepTwoView_Sample.as_view(), name='UploadArt'),
    path('<slug:c_slug>/<slug:product_slug>/medida-y-cantidad', views.StepOneView.as_view(), name='ProdDetail'),
    path('<slug:c_slug>/<slug:product_slug>/subir-arte', views.StepTwoView.as_view(), name='UploadArt'),
    path('<slug:c_slug>/<slug:product_slug>', views.AddProduct, name='AddProduct'),
    path('stickers-por-unidad/', views.AddUnitaryProduct, name='AddUnitaryProduct'),
    path('<slug:c_slug>', views.ProdCatDetail, name='ProdCatDetail'),
    path('make_review/', views.make_review_view, name='make_review_view'),
    path('prices/', views.prices, name='prices'),
    path('email_confirmation_needed/', views.email_confirmation_needed, name='email_confirmation_needed'),
    re_path(r'^confirmacion-de-correo-electronico/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
        views.activate, name='activate')
]

order URLS:

from django.urls import path from . import views

app_name = 'order'

urlpatterns = [
    # path('thanks/<int:order_id>/', views.thanks, name = 'thanks'),
    path('/gracias_pago_con_tarjeta_de_credito/', views.thanks_credit_card, name='thanks_credit_card'),
    path('/gracias_pago_con_deposito_en_efectivo/', views.thanks_deposit_payment, name='thanks_deposit_payment'),
    path('/historial_de_compras/', views.orderHistory, name = 'order_history'),
    path('/<int:order_id>/', views.viewOrder, name = 'order_detail'),
    path('/ingresos/', views.OrdersListView.as_view(), name='ingresos'), #Todas las órdenes con filtro
]

Upvotes: 0

Views: 397

Answers (2)

ruddra
ruddra

Reputation: 52008

Adding to @PabloAlbonrnoz 's answer, I think your URL definations are wrong, you need to change like this:

# in root url
path('ordenes/', include('order.urls')),

# in order url

urlpatterns = [
    # path('thanks/<int:order_id>/', views.thanks, name = 'thanks'),
    path('gracias_pago_con_tarjeta_de_credito/', views.thanks_credit_card, name='thanks_credit_card'),
    path('gracias_pago_con_deposito_en_efectivo/', views.thanks_deposit_payment, name='thanks_deposit_payment'),
    path('historial_de_compras/', views.orderHistory, name = 'order_history'),
    path('<int:order_id>/', views.viewOrder, name = 'order_detail'),
    path('ingresos', views.OrdersListView.as_view(), name='ingresos'),
]

Basically I removed / which was at beginning of the URL definitions.

Probably I don't agree with the b section of Pablo's answer. I would say to handle it in the view or form. For example:

from django.http import Http404

class AddProduct(CreateView):
     def post(self, request, *args, **kwargs);
        slug = request.kwargs.get('c_slug')
        if not slug in ['paper',  "vinyl", "laminated"]:
             return Http404('option not found')
        return super().post(request, *args, **kwargs)

Or if you don't want to have it like this, then you can follow Pablo's suggestion, then the url will be:

re_path(r'^(paper|vinyl|laminated)/(?P<product_slug>[\w-]+)$', views.AddProduct, name='AddProduct')

Upvotes: 0

fixmycode
fixmycode

Reputation: 8506

a) Django will resolve URLs in the order they're presented in your urls.py files, so I'd assume your /ordenes/ URL is below, the easiest way is to put all the /ordenes/ urls before AddProduct, so when the URL doesn't match /ordenes/ingresos/ then it will continue down the array until it matches with AddProduct

b) You can limit the AddProduct view the same way you're limiting the /confirmacion-de-correo-electronico/ view, by using re_path instead of path and defining a regular expression that represents your slugs. Maybe they're all lowercase, maybe they don't contain certain symbols.

Upvotes: 1

Related Questions