4

I would like to create a profile page for every account created. Once created the user profile can be accessed like

http://example.com/username

But before creation I should validate that the url is already available and not taken by existing url patterns. For ex: There will be a page like

http://example.com/about

Now "about" is not a valid user. But it is a valid url pattern. I should be able to prevent a user creation with a name 'about'. For that I need to check the url patterns in addition to check whether a user with that name already exists. How to do this?

An easy way out would be to have a url pattern like the following for the profile page: http://example.com/user/username

But I've a strong requirement to have profile page like the following http://example.com/username

Bharathwaaj
  • 2,627
  • 2
  • 22
  • 35
  • Can you show some of the code you currently use to validate the url? I'd say that something like `if 'about' in url: return False` might be enough, but maybe I misunderstand the question. – Junuxx Jun 26 '12 at 12:34
  • For example in urls.py, I've url(r'^admin/', include(admin.site.urls)), Now, the view function should not allow to create a user with name 'admin' although there is no existing user with that name. – Bharathwaaj Jun 26 '12 at 12:49

5 Answers5

2

You can simply try to resolve the address to a view:

from django.core.urlresolvers import resolve
from myapp.views import user_profile_view

try:
    my_view = resolve("/%s/" % user_name)
    if my_view == user_profile_view:
        # We match the user_profile_view, so that's OK.
    else:
        # oops, we have another view that is mapped on that URL
    # you already have something mapped on this address
except:
    # app doesn't have such path

EDIT:

you can also make the check in a different way:

def user_profile_view(request, user_name):
    # some code here

user_profile_view.name = "User Profile View"

and then the check above could be:

if getattr(my_view, "name", None) == "User Profile View":
    ...
Tisho
  • 8,320
  • 6
  • 44
  • 52
  • This doesn't work! It always goes to the except condition. :-( – Bharathwaaj Jun 26 '12 at 12:48
  • Oh, right. You just have to check the view name, returned by this – Tisho Jun 26 '12 at 12:49
  • url(r'^admin/', include(admin.site.urls)) try: urlresolvers.resolve("/%s" % 'admin') match = "Path already present" except: match = "doesn't match" I always get 'doesn't match' – Bharathwaaj Jun 26 '12 at 12:53
  • Yep, see my updated answer. You have a catch-all view handler for users. So you just have to check if this URL is processed by User profile view (which means that the wildcard matches), or if it is handled by another view – Tisho Jun 26 '12 at 12:57
  • It always goes to the except condition! urlresolvers.resolve always raises exception. – Bharathwaaj Jun 26 '12 at 13:06
  • Same case. It still goes to the except condition! – Bharathwaaj Jun 26 '12 at 13:08
  • Where did you paste and use the code? It should be in your 'create user' view. – Tisho Jun 26 '12 at 13:16
  • Yes. It is in 'create user' view. – Bharathwaaj Jun 26 '12 at 13:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13053/discussion-between-tisho-and-bharathwaaj) – Tisho Jun 26 '12 at 13:28
  • The url pattern requires "/" at the end. so use resolve("%s/" % user_name). Check the chat discussion for details. – Tisho Jun 26 '12 at 13:37
1

you can add custom form field validation. Look at this post. Django and Custom Form validation

raise forms.ValidationError(u'please choose another username') check and raise errors.

Or you can try setting the following as url for your users, example.com/user/<username>/

edit 1 : you can use this as a list of all invalid usernames

Community
  • 1
  • 1
pyronic
  • 372
  • 6
  • 16
0

I don't think you can check this with django.core.urlresolvers.resolve. Note that it just checks for the pattern for fixed url and not variable part of your url. In your case, you will most likely have 'username' as variable parameter that is passed to view. Pattern for this will match for non-existing username also. So the checking patterns is not good solution.

Better method will be separating out static or other pages in different namespace. e.g. http://example.com/static/about

Or you can have predefined keywords/reserved words for your site e.g. [ "about", ... ] and check it against username while creating user.

Rohan
  • 52,392
  • 12
  • 90
  • 87
0

Put your username view at the end of urls.py, so that other url rules will be checked first.

Then the easiest way is to have a list of invalid user names which should be used in user registration validation.

def clean_username(self):
    INVALID_USERNAMES = ('about', 'admin', 'register', '...')

    username = self.cleaned_data['username']
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        pass
    else:
        raise forms.ValidationError(u'%s already exists' % username )

    if username in INVALID_USERNAMES:
        raise forms.ValidationError(u'%s is not a valid username' % username )

    return username
Aidas Bendoraitis
  • 3,965
  • 1
  • 30
  • 45
0

firstly, a url rule for usernames:

url(r'^(?P<username>[-\w]+)/$', 'membership.views.profile', name='profile'),

making sure that a username doesn't conflict with an existing url rule is a little harder.

the way I usually handle this is by adding uniqueness to the url:

url(r'^user/(?P<username>[-\w]+)/$', 'membership.views.profile', name='profile'),

if you absolutely must have the url for profiles start with the username then you can try to rake the urls using a method like this one: https://stackoverflow.com/a/2094270/884453 and then make sure that username is both unique against other usernames and against routes

EDIT

as i was writing this someone posted a cool idea for a validator that makes a bunch more sense.

using from django.core.urlresolvers import resolve to check it for uniqueness is a great solution

from django.core.exceptions import ValidationError
from django.core.urlresolvers import resolve

def validate_unique_resolve(value):
    urlroute = True
    try:
        urlroute = resolve(path, urlconf)
    except urlresolvers.Resolver404:
        urlroute = False

    if urlroute != False :
        raise ValidationError(u'%s is a reserved url pattern' % value)
Community
  • 1
  • 1
Francis Yaconiello
  • 10,829
  • 2
  • 35
  • 54