Search code examples
djangocase-insensitive

case insensitive query using generic views


I would like my urls to be case insensitive. Adding (?i) to the beginning of the regexp in urls.py does not work completely when using generic views.

Here is the url that I'd like to focus on:

url(r'^(?i)(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-A-Za-z0-9_]+)/$', BlogDateDetailView.as_view(model=Entry,
 queryset=Entry.objects.all(),
 date_field='pub_date',
 slug_field='slug',
 )),

The following work:

http://mysite.com/2012/jan/24/my-article
http://mysite.com/2012/JAN/24/my-article

The following does not work (i.e I get a 404):

http://mysite.com/2012/jan/24/My-Article

I think the reason it does not work is because the lookup query for the slug is case sensitive. In order to make this work, I believe I need to subclass (not sure if this is the right term) class SingleObjectMixin(object): since this is where queryset = queryset.filter(**{slug_field: slug}) happens. Perhaps I should subclass get_queryset().

I'd appreciate some guidance on how I could do this cleanly in django 1.3


Solution

  • Case-insensitivity in URLs is generally a bad thing. A resource should only really have one URL.

    However, you can just use:

    slug_field='slug__iexact'
    

    But, I would instead catch the DoesNotExist exception, lower() the slug from the URL, try the query again with the new slug and return a redirect to the correct URL. You could actually check for uppercase letters before running the first query to avoid running unnecessary ones.

    It's up to you :)