I want to write the URLconf for a shopping cart app I wrote in django. I wonder what is the preferred way of constructing URLs.
The URL is accessible by the users via a hyperlink(They are not supposed to type it in the address bar). It adds the specified item to their shopping cart. should I
use the pk for the item:
http://example.com/add/253
or use a unique slug:
http://example.com/add/unique_item_slug
Do any of these approaches have security or performance advantage. Is there any reason to prefer one?
The main reason for using slugs is SEO (Search, Engine Optimisation). The argument is that
a search for 'My awesome widget' will return results which place -
http://example.com/products/my_awesome_widget
higher than
http://example.com/products/423
Google likes URL's that make sense to human beings. Ideally you want the URL to say as much about the page as possible. Have a look at the section 'Improve the Structure of your URLs' in googles SEO starter guide.
Since you're going to be selling things online, it's going to be important that web surfers easily find your products on search engines. Therefor the use of slugs is definitely recommended.
One disadvantage in depending solely on slugs is that you'll need to coerce the product name into an unique slug. You probably don't currently have a unique constraint on the product name, so you may have to do a bit of work creating the slug (by checking for whether the slug you're about to create already exists). A common solution is to include the slug and the product id.
http://example.com/products/my-awesome-widget/243
That way your slug doesn't have to be unique, but your url still includes the product name.
Over the modern web development, you can do use your pk in the URL and that wouldn't be a problem.
Relying in a pretty restful design I would recomend you:
http://example.com/product/253/add
where the http://example.com/product/253 is your product detailed view.
As Ewen said, the point of putting titles directly in the URL is SEO. Having keywords in the URL has a significant effect on search engine results
There isn't really any significant security risk with using the primary key in the URL, other than the ability for people to guess/predict other ones. But you shouldn't be relying on
nobody will guess this
as a security measure anyway.
Related
I searched on google and found this: "SlugField is a field for storing URL slugs in a relational database. SlugField is a column defined by the Django ORM. SlugField is actually defined within the django.db."
But still, the definition sounds a little complicated to me. I don't even know what a slug is in this context and not sure about Django ORM.
I just need a reason why I should use SlugField in Django in simple terms.
You don't strictly need to use a SlugField.
"Slug" is a term borrowed from journalism that refers to a short version of a title. As mentioned in a comment to your answer, it's a way to make URLs more explicit while still keeping them somewhat short, instead of using, for example, the full title (which would often be too long), or an ID (which wouldn't be explicit or memorable at all: think of a user who wants to find an article they remember reading: if they start typing some keyword in their address bar, a URL that contains it will pop up, one with an ID will not).
If you wanted you could craft your own slug, by making it URL-friendly (remove any symbol that a URL wouldn't hold, converting anything that would need to be url-encoded, turning spaces into hyphens...) and removing anything unnecessary (e.g. removing words like the, a, an, is, are... or cropping lenghty titles to a maximum number of words or characters).
SlugField is simply a convenience you can use to automate that to some extent. It also comes with some extra features that you might need: for example it automatically generates a slug from a field of your choice, and it can add a unique number to the slug so that you don't accidentally end up with two identical URLs for two different articles that have the same title.
The reason it is a field is that, although you could, it's not smart to calculate a slug every time you access an object: the slug will only change when the title changes, meaning possibly never, so it makes sense to generate it only once and then store it in the database to use it next time, without having to produce it again. This has the added advantage of making a URL to a certain article permanent: you could make it so the slug won't change even if you change the title of the article, which would be a good thing.
Once you have it, since a slug refers unambiguously to a specific object, it acts as a sort of human-readable unique ID, and so it can be used to retrieve the object from the database as efficiently as an opaque numeric ID. It also obscures how many objects you have (if for some reason you want to do that), since a sequential ID of, say, 1543, tells anyone that you probably have 1542 other objects that came before that one.
I could use some help creating a plan of attack for a project I'm working on.
Imagine that the site is for a group that oversees regional sales offices, distributed around the world. The purpose of this project is to let superusers spin up a new sub-site specific to each and every office, at a fast pace -- sites are added on a frequent basis. The office sub-sites should be wholly contained with "admin" users specific to that sub-site and should be user-friendly CMS. A superuser should be able to step in and manage all of these office sub-sites.
In addition to the self-contained office sub-site instance, there is also a need for each sub-site to manage contacts, leads, etc and store this in one central area for the superusers.
I've done a few sites using Django, but never anything multi-tenant. I'd like suggestions for technologies to use or tutorials/documentation that might be helpful.
Requirements:
Each sub-site uses the same source (templates, JS, available features, etc), but can be modified to reflect custom content within the templates.
Assigned subdomains (with an option of using a fully qualified domain) per sub-site, configured within the project, not in a hardcoded settings file.
Sub-site specific user access controls, in addition to superusers who can access all sub-sites.
The ability to provide an "independent" CMS for each sub-site. i.e., A sub-site admin only sees their content. My preference for this project would be django-cms, but I'm open to suggestions.
Support for apps that pool the data from all the sub-sites, but limit sub-site "admins" to only viewing their records into that app.
Considering the above, what approach would you recommend? I am open to reconsidering technologies, but I would like to stick with Python.
There is a great app called django-tenant-schemas that uses PostgreSQL schemas mechanism to create multi-tenancy.
What you get is specyfing SHARED_APPS that contain objects shared across all the schemas (sub-sites), and TENANT_APPS that contain objects specific for a sub-site, i.e. users, records etc. The schemas are completely isolated from each other.
Each PostgreSQL schema is tied to a domain url, so that middleware checks the HOST part of the request and sets the db connection's schema to appriopriate one.
In addition, it allows you to define a PUBLIC_SCHEMA_URLCONF which allows you to specify urlconf file for public schema - the meta site that is not tied to any sub-site.
Sorry for quick and dirty answer, i just share what i've done to achieve multi tenancy:
django-tenancy I like the author's approach of using "dynamic model"
django-dynamicsite This is where dynamic SITE_ID based on domain will be linked to a tenant
Both libraries above, when combined, is able to serve a django instance which is multi-tenant, and flexible. What i mean flexible here is: you can define any model whether is it "tenant" or "global". So, you can have a site with global user but per tenant product catalogue, or per tenant + product. From many django app i've tried, this is the most flexible way to achieve multi tenancy
The Django based CMS Mezzanine also has multi-tenancy support.
It has most of the features you requested except the sub-site user controls I think. The admin page can be separated by site for admin users, but the normal users not.
However, if you dont need a CMS this might be an overkill for your use-case, But I wanted to mention it here for completeness.
I have been trying to use django-tenants for a while along with Wagtail but this combination didn't work very well, or let me say, despite of a lot of try I was not able to get wagtail admin-page working correctly. I think will try to switch to django-tenant-schemas which I more widely used .
NOTE: django-tenant-schemas is not maintained now.
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:
exclude pk or any sequential ids from the url
be able to uniquely access the Item details page
I intended to ask this as a general web design question, but just thought I should mention that I am working with Python/Django.
You need to have some kind of identifier in the URL, and this identifier:
must be unique (no two objects can have the same id)
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.
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.
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.
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.
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.
I've produced a few Django sites but up until now I have been mapping individual views and URLs in urls.py.
Now I've tried to create a small custom CMS but I'm having trouble with the URLs. I have a database table (SQLite3) which contains code for the pages like a column for header, one for right menu, one for content.... so on, so on. I also have a column for the URL. How do I get Django to call the information in the database table from the URL stored in the column rather than having to code a view and the URL for every page (which obviously defeats the purpose of a CMS)?
If someone can just point me at the right part of the docs or a site which explains this it would help a lot.
Thanks all.
You dont have to to it in the flatpage-way
For models, that should be addressable, I do this:
In urls.py I have a url-mapping like
url(r'(?P<slug>[a-z1-3_]{1,})/$','cms.views.category_view', name="category-view")
in this case the regular expression (?P<slug>[a-z1-3_]{1,}) will return a variable called slug and send it to my view cms.views.category_view. In that view I query like this:
#render_to('category.html')
def category_view(request, slug):
return {'cat':Category.objects.get(slug=slug)}
(Note: I am using the annoying-decorator render_to – it is the same as render_to_response, just shorter)
Edit This should be covered by the tutorial. Here you find the url-configuration and dispatching in every detail. The djangobook also covers it. And check pythons regex module.
Of course you can use this code.
Your question is a little bit twisted, but I think what you're asking for is something similar to how django.contrib.flatpages handles this. Basically it uses middleware to catch the 404 error and then looks to see if any of the flatpages have a URL field that matches.
We did this on one site where all of the URLs were made "search engine friendly". We overrode the save() method, munged the title into this_is_the_title.html (or whatever) and then stored that in a separate table that had a URL => object class/id mapping.ng (this means it is listed before flatpages in the middleware list).
Desperate, please help. Will work for food :)
I want to be able to have pages at the following URLs, and I want to be able to look them up by their URL (ie, If somebody goes to a certain URL, I want to be able to check for a page there).
mysite.com/somepage/somesubpage/somesubsubpage/
mysite.com/somepage/somesubpage/anothersubpage/
mysite.com/somepage/somesubpage/somesubpage/
mysite.com/somepage/somepage/
Notice I want to be able to reuse each page's slug (ie, somepage/somepage). Of course each slug will be unique for it's level (ie, cannot have two pages with mysite.com/somepage/other/ and mysite.com/somepage/other/ because they would in essence be the same page). What is a good way to do this. I've tried to store the slug for a page ('somesubpage') in a field called 'slug', and make each slug unique for it's parent page so that the above circumstance can't happen. The problem with this is that if I try to look up a page by it's slug (ie, 'somepage'), and there happens to be a page at mysite.com/other/somepage/ and mysite.com/page/somepage/, how would my application know which one to get (they both have the same slug 'somepage').
You need to also store level and parent attributes, so that you can always get the right object.
The requirement to store hierarchical data comes up very frequently, and I always recommend django-mptt. It's the Django implementation of an efficient algorithm for storing hierarchical data in a database. I've used it on several projects. Basically, as well as storing level and parent, it also stores a left and right for each object, so that it can describe the tree and all its sub-elements uniquely. There are some explanatory links on the project's home page.
It sounds like you're looking for a CMS app. There's a comparison of several Django-based CMS. If you want a full-featured CMS at the center of your project, DjangoCMS 2 or django-page-cms might be the right fit. If you prefer a CMS that supports the basic CMS use cases but goes out of your way most of the time feincms could be something to look at.
edit: incidentally, most of the CMS on the comparision page use django-mptt that Daniel mentions.