Skip to content Skip to sidebar Skip to footer

Url Design: Ways To Hide Pk/id From Url

To access the details page of an Item on my site, one would use the following url /item/1 where 1 is the primary key of the Item I am looking for a solution that a

Solution 1:

You need to have some kind of identifier in the URL, and this identifier:

  1. must be unique (no two objects can have the same id)
  2. must be permanent (the id for an object can never change)

so there aren't all that many options, and the object's primary key is the best choice. If for some reason you can't use that (why not?) you can encode or obfuscate it: see this question and its answers for some ideas about how to do that.

Stack Overflow's own URL design is worth a look. You can reach this question via any URL of the form

https://stackoverflow.com/questions/9897050/any-text-you-like-here!

This allows the URL to contain keywords from the question's title (for search engines) while also being able to change when the title changes without breaking old links.

Solution 2:

I don't like the slugfield option because it adds an additional query to the database.

I did the following in a project:

My URL looks like this:

<domain>/item/5927/728e26e9464a171b228bc9884ba3e4f76e2f8866/

This is:

<domain>/item/<id>/<hash>/

If you don't know the hash you can't get to the item:

urls.py:

url(r'^item/(?P<id>\d+)/(?P<hash>\w+)/$', 'rwapp.views.item', name='item')

views.py:

from hashlib import sha1

defitem(request,id=None,hash=None):
    ifnotid:
        return HttpResponseRedirect("/home")
    ifhash:
        chash = sha1("secret_word%s"%id).hexdigest()
        ifnot chash==hash:
            return HttpResponseRedirect("/home")
    else:
        return HttpResponseRedirect("/home")

Of course, every time you render the URL you have to add the // part.

Solution 3:

For Django, you can give your models a SlugField, then have the view look up the model using that.

MyModel.objects.filter(slug_field_name='some-slug-value')

Make sure some form of uniqueness constraint is on it.

Solution 4:

Well there are a lot ways to do this. Since you are using django, take a look at SlugField. Or you generate UUID and store it on each item for access.

Solution 5:

One dirty way of doing this would be to use a cookie to hold the id of the object being requested. I don't particularly like the idea and it might be very difficult to get a framework to support unless you have experience writing/extending frameworks.

Some frameworks support using an id= attribute instead of your URL path. If this is included as a POST parameter it will not be visible, but linking pages together with POST would be challenging as it is intended for the submission of form data.

The method I would suggest, is to use something besides ids to uniquely identify your objects if this is a real requirement. Then include that in your URL. While this is not an ideal design from the database perspective it does have benefits. First you must consider why you want to hide this information. If it is for SEO purposes, using a name of the item rather than its id is what you want in the URL. The real problem is that if you just hide this information in some other data channel you then have the same URL for different resources. This is sub-par for many reason not the least of which is SEO and user bookmarks. Using a human readable key resolves both situations and others, while infuriating your DBA. Using this method should also work easily into a framework either directly or by using additional code in the controller to make the translation, which might set you right with the DBA.

Post a Comment for "Url Design: Ways To Hide Pk/id From Url"