How to create a WordPress like URL naming convention in Django? - django

I'm a newbie in Django and in WordPress if you create a Post called "hello world" then the URL by default will be like
wordpress.com/2012/07/05/hello-world/
and if you create another post with the same name it will be
wordpress.com/2012/07/05/hello-world-2/
I want to achieve the same in Django and I was thinking to create a sample urlconf like this
(r'^articles/(\d{4})/(\d{2})/(?P<name>\w+)', 'article.views.article_detail')
and in the views break down the name and iterate through all the items and match the name.
But the problem with will be that I won't be able to reference posts dynamically. For e.g. if I was to link the a hello world post I would need to find out how many posts with the same name exist already and then append the additional number to it which is inefficient.
So what's the best way to do this in Django?

See the documentation for Django's {{ url }} template tag. It lets you pass it a view name and parameters, and automatically generates the correct URL for you.
You can take care of appending numbers to each post's name in the function that generates its slug - you could have a look at django-autoslug

Related

How to pass around variables without url parameters in Django?

My question is, how could I go about passing information in django from the template to a view without url parameters. I know that sessions can help me do this however, I can't find any resources online that show how to create a key value pair in the sessions from within a template. For example, If I had a link
{{ c.class_id }}
which would lead you to a specific university class homepage, how could I pass along c.class_id to the view that is responsible for rendering this specific homepage? Would I have to put this link inside a form and then POST it to the view?
You can use GET parameters. Example:
{{ c.class_id }}
To retrieve the parameter from the Django view, use:
param_value = request.GET['param_name']

'Hiding' form query from URL (Django 1.3)

I have a form with 6-7 fields. After user input, my webapp searches for those fields in a database and displays the results.
Now the issue is, that the URL ends up having all the form field names and their values in it.
result/?name=lorem&class=arc&course=ipsum
Now with the form having 7-8 fields the url ends up looking ugly.
Is there a Django technique to 'hide' these from the URL? Quotes around hide because I'd be okay with a completely different way to pass the objects to my database from the form as well.
Use a POST request. Here's the django docs on forms and a specific example using POST>. HTML-wise, all you need to do is change the method on the form tag.
I do not recommend to use POST requests for search. If you'll use GET it will be easer for user, he can just bookmark a link and save search or share search results with friends.

How to organize URLs in django for views handling GET data and parsing URL?

I have a view that displays some movie data. I thought that it might be a good idea to have a view handle a an URL like movie-id/1234 to search for movie id 1234. Furthermore I would like to be able to enter the ID into a form and send that to a server and search for it. To do that I created a second entry in the urls.py file shown below.
urlpatterns = patterns('',
url(r'movie-id/(?P<movie_id>.+?)/$', 'movieMan.views.detailMovie'),
url(r'movie-id/$', 'movieMan.views.detailMovie', name='movieMan.detailMovie.post'),
)
So if I want to pass data to my view either via a URL or a GET or POST request I have to enter two urls or is there a more elegant way? In the view's code I am then checking if there is any GET data in the incoming request.
To make the second url usable with the template engine, where I wanted to specify the view's url using the {% url movieMan.detailMovie.post %} syntax I had to introduce a name attribute on this url to distinguish between these two.
I am not sure if I am thinking too complicated here. I am now asking myself what is the first url entry good for? Is there a way to get the URL of a movie directly? When do these kinds of URLs come into play and how would they be generated in the template ?
Furthermore I would like to be able to enter the ID into a form and
send that to a server and search for it.
Is this actually a search? Because if you know the ID, and the ID is a part of the URL, you could just have a textbox where the user can write in the ID, and you do a redirect with javascript to the 'correct' URL. If the ID doesn't exist, the view should return a Http404.
If you mean an actual search, i.e. the user submitting a query string, you'll need some kind of list/result view, in which case you'll be generating all the links to the specific results, which you will be sure are correct.
I don't think there is a more elegant way.
I did almost the same thing:
url( r'^movies/search/((?P<query_string>[^/]+)/)?$', 'mediadb.views.search_movies' ),
The url pattern matches urls with or without a search parameter.
In the view-function, you will have to check whether the parameter was defined in the url or in the query string.

Use url args in views, is it possible?

I'd like to use url arguments in views (not templates, I know how to do that).
So is it possible to use them like:
def item_link(self, item):
return mainpage_url_name + "%s/%i" % (item.slug, item.cid)
mainpage_url_name - is of course defined in url patterns (as name variable)
I'm a total newb in Django...
Thanks
First you should use names for your url patterns as documented here.
Then you can use reverse() to use these names in your views or methods.
Following your comments you are using the syndication framework.
Therefore you should make sure that you define get_absolute_url() for you models, ideally using the permalink decorator (for a clean reversing of your urls).
Looking at the example from Django's docs that should be all that's necessary.
To specify the contents of <link>, you
have two options. For each item in
items(), Django first tries calling
the item_link() method on the Feed
class. In a similar way to the title
and description, it is passed it a
single parameter, item. If that method
doesn't exist, Django tries executing
a get_absolute_url() method on that
object.

Validating URL slugs

I'm creating an app in which many urls are using a pattern like /foo/bar/<object_id>/<object_name_slug>/, like many applications (SO included), which is itself a straightforward pattern to implement. However, I don't want to just blindly ignore the contents of the slug field and open the app up to stupid stuff like people distributing a doctored URL (e.g. the recently popular http://www.independent.co.uk/life-style/food-and-drink/utter-PR-fiction-but-people-love-this-shit-so-fuck-it-lets-just-print-it-2269573.html).
My plan is to validate the slug an issue a redirect to the correct URL if someone reaches a page via a bad slug (again, like SO). This would be trivial to implement in the view, but since this will be a pattern used on many views, I'd like to factor it out into something reusable--probably a decorator or a middleware.
What's the best way to do this? Could a decorator determine which url pattern was matched by a particular request so that it could generate a reverse if necessary?
Thanks for the ideas.
You could use middleware for this. Cross-check the Entry id (let's just suppose you use the Entry model for content. The ID in the URL you mention would be 2269573 for example) with its slug (supposing your Entry model has a slug field of course). If the slug is incorrect, just redirect to the correct page.
In order to do this, create a class, and give it the process_request method. Then add this class to your settings' MIDDLEWARE_CLASSES.
The process_request takes a "request" parameter (a HttpRequest object), and this object has a path attribute that will give you the URL that was requested.
Based on that URL you can define the actions to be undertaken.
The method of your middleware class should return None or a HttpRequest object. The latter can be a django.http.HttpResponseRedirect instance, meaning you can redirect to the correct URL (thereby ignoring the incorrect slug).