Kakar
Kakar

Reputation: 5609

How to pass special characters in the urls in django

Suppose I want to pass the username in the url:

username  = '[email protected]'

So in the urls, its like this:

url(r'(?P<user_name>\w+)/$', 'user_related.views.profile', name='profile'),

And to fetch that user, in the views.py:

def profile(request, user_name):
    user = User.objects.get(username=user_name)

    return render(request, 'user_profile.html', {'user':user})

But I get an error:

User matching query does not exist.

Because django automatically converts @ into %40. How can I pass the actual username to the view? Please help me solve this problem. Thank you!

Upvotes: 3

Views: 7968

Answers (3)

iragm
iragm

Reputation: 61

The existing answer is missing a couple things, but I don't have enough rep to comment or edit it. Here is a working solution:

For function based views:

In views.py:

# this is incorrect for current versions of Django in the other answer
from urllib.parse import unquote

def profile(request, user_name):
    user = User.objects.get(username=unquote(user_name))
    return render(request, 'user_profile.html', {'user':user})

Then, in urls.py, we can skip regex altogether:

from django.urls import path
urlpatterns = [
    path('users/<str:user_name>/', views.profile, name='profile'),
    # ... put more urls here...
]

That's pretty much it for function based views. But I am using class based views, which look a tiny bit different. Here is what I did to get this working with class based views:

In views.py:

from urllib.parse import unquote
from django.views.generic import DetailView

class Profile(DetailView):
    """Display the user's profile"""
    template_name = 'user_profile.html'
    model = User

    def dispatch(self, request, *args, **kwargs):
        self.username = kwargs['user_name']
        return super().dispatch(request, *args, **kwargs)

    def get_object(self, *args, **kwargs):
        try:
            return User.objects.get(username=unquote(self.username))
        except:
            raise Http404

And when using class based views, your urls.py:

from django.urls import path
urlpatterns = [
    path('users/<str:user_name>/', views.Profile.as_view(), name='profile'),
    # ... put more urls here...
]

Upvotes: 3

Ramesh Ponnusamy
Ramesh Ponnusamy

Reputation: 1807

Specify the string by using w

url(r'^url_name/(?P<param_name>[\w\@%-+]+)/$',url_method,name='end_point_name')

Upvotes: 0

catavaran
catavaran

Reputation: 45595

Use unquote function from standard urllib module:

from urllib import unquote

user = User.objects.get(username=unquote(user_name))

BTW, as far as I understand regex in your url() should be [\w@%.]+. Plain \w+ do not match [email protected] and kakar%40gmail.com.

Upvotes: 7

Related Questions