MaxCore
MaxCore

Reputation: 2738

Django passes known an exact string as a url parameter

I have two urls in dispatcher pointing the same view:

path('posts/top/', posts, name='top'),
path('posts/new/', posts, name='new'),

I want view start as follows:

def posts(request, ordering):
    ...

I guess, to pass top and new as a parameter it should be something like:

path('posts/<ordering:top>/', posts, name='top'),
path('posts/<ordering:new>/', posts, name='new'),

But it gives me:

django.core.exceptions.ImproperlyConfigured: URL route 'posts/<ordering:top>/' uses invalid converter 'ordering'.

So, as a work around I use this, but it looks a little bit dirty:

path('posts/top/', posts, name='top', kwargs={'order': 'top'}),
path('posts/new/', posts, name='new', kwargs={'order': 'new'}),

What is the right way to do it?

Upvotes: 7

Views: 12997

Answers (2)

I got the same error below:

django.core.exceptions.ImproperlyConfigured: URL route 'test/<id:id>/' uses invalid converter 'id'.

Because I use id as a converter as shown below:

urlpatterns = [
    path('test/<id:id>/', views.test, name="test")
]              # ↑ Converter

So, I use int as a converter as shown below, then the error was solved:

urlpatterns = [
    path('test/<int:id>/', views.test, name="test")
]              # ↑ Converter

In addition, str, int, slug, uuid and path converters are available by default according to the doc.

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599610

You've misunderstood the way path converters work. The first element is the type, which here is str, and the second is the parameter name to use when calling the view. At this point you don't constrain the permissible values themselves. So your path would be:

path('posts/<str:ordering>/', posts, name='posts')

and when you come to reverse you would pass in the relevant parameter:

{% url 'posts' ordering='top' %}

If you really want to ensure that people can only pass those two values, you can either check it programmatically in the view, or you can use re_path to use regex in your path:

re_path(r'^posts/(?P<ordering>top|new)/$', posts, name='posts')

Upvotes: 22

Related Questions