Reputation: 17067
To access the details page of an Item on my site, one would use the following url
<mydomain>/item/1
where 1
is the primary key of the Item
I am looking for a solution that allows me to redesign the url with the following requirements:
I intended to ask this as a general web design question, but just thought I should mention that I am working with Python/Django.
Upvotes: 7
Views: 15359
Reputation: 1373
I think this is exactly what https://hashids.org/ are for.
Generate short unique ids from integers
Hashids is a small open-source library that generates short, unique, non-sequential ids from numbers.
It converts numbers like 347 into strings like “yr8”, or array of numbers like [27, 986] into “3kTMd”.
Upvotes: 0
Reputation: 1638
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
def item(request,id=None,hash=None):
if not id:
return HttpResponseRedirect("/home")
if hash:
chash = sha1("secret_word%s"%id).hexdigest()
if not chash==hash:
return HttpResponseRedirect("/home")
else:
return HttpResponseRedirect("/home")
Of course, every time you render the URL you have to add the // part.
Upvotes: 6
Reputation: 65854
You need to have some kind of identifier in the URL, and this identifier:
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.
Upvotes: 8
Reputation: 2459
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.
Upvotes: 0
Reputation: 2977
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.
Upvotes: 5
Reputation: 32404
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.
Upvotes: 4