Search code examples
pythondjangodjango-viewsdjango-urls

django 2.2.5 URL regex in url path


I would like to support the above views in a single view in url ...in my search I came across this post which is no longer supported and all the tutorials i've found have been outdated, which demonstrate how to accomplish the task in django 1.8.3.

In 'products/views.py' I have created a views for products and details. ProductListView will display all products, while ProductDetailView will display a single product detail (title, description, price etc).

products/views.py

class ProductListView(ListView):
    queryset = Product.objects.all()
    template_name = "products/list.html"


class ProductDetailView(DetailView):
    queryset = Product.objects.all()
    template_name = "products/detail.html"

products/urls.py include path to the views for ProductListView and ProductDetailView. ProductListView appears to be correct. ProductDetailView is incorrect! I'm getting the following warnings:

WARNINGS: ?: (2_0.W001) Your URL pattern '^products/(?P\d+)/$' [name='details'] has a route that contains '(?P<', begins with a '^', or ends with a '$'. This was likely an oversight when migrating to django.urls.path().

ecommerce.py/urls.py is where i've included products and details urls

ecommerce/urls.py:

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

from .views import home, about, contact

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home, name='home'),
    path('about/', about, name='about'),
    path('products/', include('products.urls'), name='products'),
    path('products/', include('products.urls'), name='details'),
    path('contact/', contact, name='contact'),
    path('account/', include('allauth.urls'), name='login'),
    path('register/', include('allauth.urls'), name='register'),

              ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)



products/urls.py

    from django.urls import path
    from .import views

    urlpatterns = [
        path('', views.ProductListView.as_view(), name='products'),
        path(r'^products/(?P<id>\d+)/$', views.ProductDetailView.as_view(), name='details')
    ]

Solution

  • You've got that warning because Django unable to match the url to any of your urlpattern. Shortly you can use this to solve your problem:

    # products/urls.py
    
    from django.urls import path
    from .import views
    
    urlpatterns = [
        path('', views.ProductListView.as_view(), name='products'),
        path('products/<int:pk>/$', views.ProductDetailView.as_view(), name='details')
    ]
    

    or if you want to use regex to match your url then:

    # products/urls.py
    
    from django.urls import path, re_path
    from .import views
    
    urlpatterns = [
        path('', views.ProductListView.as_view(), name='products'),
        re_path(r'^products/(?P<pk>\d+)/$', views.ProductDetailView.as_view(), name='details')
    ]
    

    The reason is because your ProductDetailView are inheriting from DetailView of Django. That View already implemented some mixin to get the object from pk key instead of id that's why when you change to use <int:pk> it'll works.

    You can take a look at the source code to see how Django implementing to query the object. (Keep you eyes on SingleObjectMixin mixin and property pk_url_kwarg = 'pk'.

    I also recommend you to change the value of pk_url_kwarg in ProductDetailView view and also remember to change pk in the urlpattern into the new value which match with pk_url_kwarg value.