308
votes
Locked. This question and its answers arelocked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.

Inspired by the question series 'Hidden features of ...', I am curious to hear about your favorite Django tips or lesser known but useful features you know of.

  • Please, include only one tip per answer.
  • Add Django version requirements if there are any.
0
    Comments disabled on deleted / locked posts / reviews | 

    55 Answers55

    221
    votes

    I'm just going to start with a tip from myself :)

    Use os.path.dirname() in settings.py to avoid hardcoded dirnames.

    Don't hardcode path's in your settings.py if you want to run your project in different locations. Use the following code in settings.py if your templates and static files are located within the Django project directory:

    # settings.pyimport osPROJECT_DIR = os.path.dirname(__file__)...STATIC_DOC_ROOT = os.path.join(PROJECT_DIR, "static")...TEMPLATE_DIRS = (    os.path.join(PROJECT_DIR, "templates"),)

    Credits: I got this tip from the screencast 'Django From the Ground Up'.

    answeredFeb 15, 2009 at 10:15
    Haes's user avatar
    Sign up to request clarification or add additional context in comments.

    14 Comments

    You shouldn't downvote people that answer their own questions. It is encouraged, even if it is pre-determined.
    This is such a good idea that I still have a hard time understanding why it's not default. How many folks test and deploy on the same machine?
    This alleviates you from always type os.path.join() which gets annoying pretty fast:j = lambda filename: os.path.join(PROJECT_DIR, filename). Then you just need to typej("static").
    If you are on Windows then replace the backslashes: os.path.join(PROJECT_DIR, "templates").replace('\\','/')
    If you really like to get this fixed in Django leave a comment tocode.djangoproject.com/ticket/694 asking core devs to reconsider thewontfix decision.
    |
    128
    votes

    InstallDjango Command Extensions andpygraphviz and then issue the following command to get a really nice looking Django model visualization:

    ./manage.py graph_models -a -g -o my_project.png
    answeredFeb 15, 2009 at 21:18
    Haes's user avatar

    4 Comments

    Nice, couldn't get the pygraphviz to install correctly in windows, but can still covert from the dot file using graphviz.
    I love sharing model diagrams with this definitely a +1
    Is there an svg option for this?
    output image seems to be busted now
    119
    votes

    Usedjango-annoying'srender_to decorator instead ofrender_to_response.

    @render_to('template.html')def foo(request):    bars = Bar.objects.all()    if request.user.is_authenticated():        return HttpResponseRedirect("/some/url/")    else:        return {'bars': bars}# equals todef foo(request):    bars = Bar.objects.all()    if request.user.is_authenticated():        return HttpResponseRedirect("/some/url/")    else:        return render_to_response('template.html',                              {'bars': bars},                              context_instance=RequestContext(request))

    Edited to point out that returning an HttpResponse (such as a redirect) will short circuit the decorator and work just as you expect.

    Jiaaro's user avatar
    Jiaaro
    77.5k43 gold badges177 silver badges191 bronze badges
    answeredFeb 15, 2009 at 16:06
    user20955's user avatar

    10 Comments

    @becomingGuru - it happens automatically.
    This is fine, unless you are returning some HttpResponseRedirect()s and some render_to_response()s. Then the redirects fail.
    I don't like it. "Explicit is better than implicit". The decorator is not telling when exactly it is going to render_to.
    @Matthew Schinckel it actually doesn't mess up redirects - if you return an HttpResponse object it just passes it along without modifying it
    I believe this approach is now redundant as of Django 1.3, see django.shortcuts.render()docs.djangoproject.com/en/dev/topics/http/shortcuts/#render
    |
    101
    votes

    There's a set of custom tags I use all over my site's templates. Looking for a way to autoload it (DRY, remember?), I found the following:

    from django import templatetemplate.add_to_builtins('project.app.templatetags.custom_tag_module')

    If you put this in a module that's loaded by default (your main urlconf for instance), you'll have the tags and filters from your custom tag module available in any template, without using{% load custom_tag_module %}.

    The argument passed totemplate.add_to_builtins() can be any module path; your custom tag module doesn't have to live in a specific application. For example, it can also be a module in your project's root directory (eg.'project.custom_tag_module').

    answeredJun 3, 2009 at 18:34
    Steef's user avatar

    3 Comments

    @Steef, you just saved me loads of time/heartache/bytes, thanks.
    Really nice. Thanks. Also a repository of custom tags would be great to share stuff, dont you think?
    That's great until someone else has to maintain your code. Think: "principle of least magic"
    96
    votes

    Virtualenv + Python = life saver if you are working on multiple Django projects and there is a possibility that they all don't depend on the same version of Django/an application.

    Peter Mortensen's user avatar
    Peter Mortensen
    31.4k22 gold badges110 silver badges134 bronze badges
    answeredJun 3, 2009 at 18:44
    phillc's user avatar

    2 Comments

    Could you add some tutorial links for virtualenv with django?
    @BozoJoe: Do this in your terminal:virtualenv myNewEnv --no-site-packages;. myNewEnv/bin/activate;pip install django; And it just works!
    87
    votes

    Don't hard-code your URLs!

    Useurl names instead, and thereverse function to get the URL itself.

    When you define your URL mappings, give names to your URLs.

    urlpatterns += ('project.application.views'   url( r'^something/$', 'view_function', name="url-name" ),   ....)

    Make sure the name is unique per URL.

    I usually have a consistent format "project-appplication-view", e.g. "cbx-forum-thread" for a thread view.

    UPDATE (shamelessly stealingayaz's addition):

    This name can be used in templates with theurl tag.

    answeredFeb 17, 2009 at 19:34
    hasen's user avatar

    5 Comments

    I agree 100% on this one. I started out using hard coded urls, and it bit me on a project when I changed the url format around a bit to accommodate some changes. I took the time to go back and dig through everything and replace hard coded urls. My only big complaint is that url tag errors kill the whole page while hard coded only messes up the individual link.
    This shouldn't be a hidden feature, this is best practice and the only way to fly.
    @skyl It's hardly "the only way to fly". I was at a Django dev sprint and Adrian Holovaty (one of the creators of Django) said he doesn't even use theurl tag... His stance is that urls shouldn't be changing anyway (if you want to be friendly to your users).
    you can use this in templates, too, as in{% url path.to.view.name arg1 arg2 %}docs.djangoproject.com/en/dev/ref/templates/builtins/…
    If you use jinja2, just addreverse like thisenvironment.filters['url'] = django.core.urlresolvers.reverse and you can use it in your templates like so:{{ 'view-name'|url(arg1, arg2)|e }} (the "e" is needed to escape some characters for inclusion in HTML)
    81
    votes

    Usedjango debug toolbar. For example, it allows to view all SQL queries performed while rendering view and you can also view stacktrace for any of them.

    Dan Abramov's user avatar
    Dan Abramov
    269k87 gold badges418 silver badges524 bronze badges
    answeredJun 3, 2009 at 18:53
    Eugene Morozov's user avatar

    Comments

    79
    votes

    Don't write your own login pages. If you're using django.contrib.auth.

    The real, dirty secret is that if you're also using django.contrib.admin, and django.template.loaders.app_directories.load_template_source is in your template loaders,you can get your templates free too!

    # somewhere in urls.pyurlpatterns += patterns('django.contrib.auth',    (r'^accounts/login/$','views.login', {'template_name': 'admin/login.html'}),    (r'^accounts/logout/$','views.logout'),)
    answeredFeb 18, 2009 at 5:37
    SingleNegationElimination's user avatar

    1 Comment

    Cool! I didn't know that we can reuse the admins login page. Thanks!
    66
    votes

    Context processors are awesome.

    Say you have a different user model and you want to includethat in every response. Instead of doing this:

    def myview(request, arg, arg2=None, template='my/template.html'):    ''' My view... '''    response = dict()    myuser = MyUser.objects.get(user=request.user)    response['my_user'] = myuser    ...    return render_to_response(template,                              response,                              context_instance=RequestContext(request))

    Context processes give you the ability to pass any variable to yourtemplates. I typically put mine in'my_project/apps/core/context.py:

    def my_context(request):    try:        return dict(my_user=MyUser.objects.get(user=request.user))    except ObjectNotFound:        return dict(my_user='')

    In yoursettings.py add the following line to yourTEMPLATE_CONTEXT_PROCESSORS

    TEMPLATE_CONTEXT_PROCESSORS = (    'my_project.apps.core.context.my_context',    ...)

    Now every time a request is made it includes themy_user key automatically.

    Alsosignals win.

    I wrote a blog post about this a few months ago so I'm just going to cut and paste:

    Out of the box Django gives you several signals that areincredibly useful. You have the ability to do things pre andpost save, init, delete, or even when a request is beingprocessed. So lets get away from the concepts anddemonstrate how these are used. Say we’ve got a blog

    from django.utils.translation import ugettext_lazy as _class Post(models.Model):    title = models.CharField(_('title'), max_length=255)    body = models.TextField(_('body'))    created = models.DateTimeField(auto_now_add=True)

    So somehow you want to notify one of the many blog-pingingservices we’ve made a new post, rebuild the most recentposts cache, and tweet about it. Well with signals you havethe ability to do all of this without having to add anymethods to the Post class.

    import twitterfrom django.core.cache import cachefrom django.db.models.signals import post_savefrom django.conf import settingsdef posted_blog(sender, created=None, instance=None, **kwargs):    ''' Listens for a blog post to save and alerts some services. '''    if (created and instance is not None):        tweet = 'New blog post! %s' instance.title        t = twitter.PostUpdate(settings.TWITTER_USER,                               settings.TWITTER_PASSWD,                               tweet)        cache.set(instance.cache_key, instance, 60*5)       # send pingbacks       # ...       # whatever else    else:        cache.delete(instance.cache_key)post_save.connect(posted_blog, sender=Post)

    There we go, by defining that function and using thepost_init signal to connect the function to the Post modeland execute it after it has been saved.

    Stephen Fuhry's user avatar
    Stephen Fuhry
    13.1k6 gold badges59 silver badges57 bronze badges
    answeredAug 19, 2009 at 13:53
    notzach's user avatar

    5 Comments

    Django's Signals are a must-have feature for me these days, when comparing web frameworks. Writing a loosely coupled forum, say, that can listen for, say, updates from a "signature" module, but not actually require that module to work, and that can also work with compatible modules implementing the same feature, is great. I don't know why signals aren't more well known and popular.
    Signals are very important to avoid tight coupling and code mess in general if we use some reusable apps in our project. You provided an excellent example for loose coupling of django apps, +1 for this.
    Do you know if signals are async ?
    "Say you have a different user model and you want to include that in every response." - Put the user into thesession. That saves you a database hit for every request.
    Signals' calls are synchronous. In my opinion, some sort of asynchronous job mechanism is more suitable for, say, publishing on Twitter/Facebook/etc (ie - rabbitmq), so users of out website don't hang on request.
    58
    votes

    When I was starting out, I didn't know that there was aPaginator, make sure you know of its existence!!

    answeredFeb 18, 2009 at 21:54
    hasen's user avatar

    Comments

    46
    votes

    UseIPython to jump into your code at any level and debug using the power of IPython. Once you have installed IPython just put this code in wherever you want to debug:

    from IPython.Shell import IPShellEmbed; IPShellEmbed()()

    Then, refresh the page, go to your runserver window and you will be in an interactive IPython window.

    I have a snippet set up in TextMate so I just type ipshell and hit tab. I couldn't live without it.

    community wiki

    3 Comments

    Better installipdb and then just typeipdb.set_trace()
    Or use Eclipse / PyDev's debugger. :-)
    import ipdb; ipdb.set_trace() FTW!
    43
    votes

    Run a development SMTP server that will just output whatever is sent to it (if you don't want to actually install SMTP on your dev server.)

    command line:

    python -m smtpd -n -c DebuggingServer localhost:1025
    community wiki

    3 Comments

    you can use console and file email backends in django 1.2 for the same purpose
    outstanding! perfect for registration! +1
    Alternative in Django 1.2 with settings:EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ..that will print the email to themanage.py output.
    41
    votes

    From thedjango-admin documentation:

    If you use the Bash shell, consider installing the Django bash completion script, which lives inextras/django_bash_completion in the Django distribution. It enables tab-completion ofdjango-admin.py andmanage.py commands, so you can, for instance...

    • Typedjango-admin.py.
    • Press [TAB] to see all available options.
    • Typesql, then [TAB], to see all available options whose names start withsql.
    answeredJul 1, 2009 at 4:27
    John's user avatar

    1 Comment

    This is in by default in newer Ubuntu's at least. :-) I was amazed when it first came out of nowhere.
    40
    votes

    The./manage.py runserver_plus facilty which comes withdjango_extensions is truly awesome.

    It creates an enhanced debug page that, amongst other things, uses the Werkzeug debugger to create interactive debugging consoles for each point in the stack (see screenshot). It also provides a very useful convenience debugging methoddump() for displaying information about an object/frame.

    enter image description here

    To install, you can use pip:

    pip install django_extensionspip install Werkzeug

    Then add'django_extensions' to yourINSTALLED_APPS tuple insettings.py and start the development server with the new extension:

    ./manage.py runserver_plus

    This will change the way you debug.

    Comments

    37
    votes

    I like to use the Python debugger pdb to debug Django projects.

    This is a helpful link for learning how to use it:http://www.ferg.org/papers/debugging_in_python.html

    answeredFeb 15, 2009 at 16:20
    Harold's user avatar

    1 Comment

    This is a godsend. To give a little more info, just add this: "import pdb; pdb.set_trace()" on any line of your code. Refresh your page. It will hang. Now go to your terminal window where you are running the development server. It should now be a interactive shell where you can access all variables as they are at that point in your code where you pasted the debug code.
    37
    votes

    When trying to exchange data between Django and another application,request.raw_post_data is a good friend. Use it to receive and custom-process, say, XML data.

    Documentation:http://docs.djangoproject.com/en/dev/ref/request-response/

    Peter Mortensen's user avatar
    Peter Mortensen
    31.4k22 gold badges110 silver badges134 bronze badges
    answeredApr 2, 2009 at 10:30
    chefsmart's user avatar

    Comments

    36
    votes

    UseJinja2 alongside Django.

    If you find the Django template language extremely restricting (like me!) then you don't have to be stuck with it. Django is flexible, and the template language is loosely coupled to the rest of the system, so just plug-in another template language and use it to render your http responses!

    I useJinja2, it's almost like a powered-up version of the django template language, it uses the same syntax, and allows you to use expressions in if statements! no more making a custom if-tags such asif_item_in_list! you can simply say%{ if item in list %}, or{% if object.field < 10 %}.

    But that's not all; it has many more features to ease template creation, that I can't go though all of them in here.

    answeredFeb 15, 2009 at 16:30
    hasen's user avatar

    6 Comments

    I use and enjoy Jinja2 as well, but I've found that there are some couplings to the "contrib" applications. Particularly, the admin tool is pretty heavily tied to Django templates. Also, I had to recreate the login decorators in contrib.auth to be Jinja2 friendly, but not too hard.
    Don't replace the template system with jinja2, just "add" it, don't remove the django templtes. Use Jinja2 for your own views, and let the admin interface continue to use the django template language.
    I agree hartily with this. Django's limited syntax is tolerable, most of the time, but when you get to the point of making custom tags and find out just how hard that actually is, Jinja2 is a breath of fresh air
    Also, if you want to doany metaprogramming on template source, Jinja2 is much more pleasant, since you can directly access the AST of parsed templates. Walking the AST makes tasks like finding out which templates extend a base template, or listing the unbound variables in a template source block, almost trivially easy.
    Thankfully in Django 1.2 the IF tag is alot smarter
    |
    35
    votes

    Addassert False in your view code to dump debug information.

    answeredFeb 15, 2009 at 20:06
    zgoda's user avatar

    7 Comments

    I think assert False is more intuitive =D
    if you're running your project in the django dev server, use python's pdb module. It's a much more powerful way to debug: import pdb; pdb.stack_trace()
    pdb is very useful, you are likely to have your connections time out unless you're very fast at debugging.
    I always use5 / 0 myself. Why five? No idea.
    @StephenPaulger really? My browser (firefox /w firebug) seems content to wait several minutes for a response while I debug.
    |
    34
    votes

    This adds to the reply above aboutDjango URL names and reverse URL dispatching.

    The URL names can also be effectively used within templates. For example, for a given URL pattern:

    url(r'(?P<project_id>\d+)/team/$', 'project_team', name='project_team')

    you can have the following in templates:

    <a href="{% url project_team project.id %}">Team</a>
    answeredFeb 18, 2009 at 7:07
    ayaz's user avatar

    Comments

    27
    votes

    Since Django "views" only need to be callables that return an HttpResponse, you can easily create class-based views like those in Ruby on Rails and other frameworks.

    There are several ways to create class-based views, here's my favorite:

    from django import httpclass RestView(object):    methods = ('GET', 'HEAD')    @classmethod    def dispatch(cls, request, *args, **kwargs):        resource = cls()        if request.method.lower() not in (method.lower() for method in resource.methods):            return http.HttpResponseNotAllowed(resource.methods)        try:            method = getattr(resource, request.method.lower())        except AttributeError:            raise Exception("View method `%s` does not exist." % request.method.lower())        if not callable(method):            raise Exception("View method `%s` is not callable." % request.method.lower())        return method(request, *args, **kwargs)    def get(self, request, *args, **kwargs):        return http.HttpResponse()    def head(self, request, *args, **kwargs):        response = self.get(request, *args, **kwargs)        response.content = ''        return response

    You can add all sorts of other stuff like conditional request handling and authorization in your base view.

    Once you've got your views setup your urls.py will look something like this:

    from django.conf.urls.defaults import *from views import MyRestViewurlpatterns = patterns('',    (r'^restview/', MyRestView.dispatch),)

    3 Comments

    FWIW, the django authors actually use class-based views in a few places, e.g. contrib.formtools:code.djangoproject.com/browser/django/trunk/django/contrib/…
    If you add acall method you could create a class called RestfulResource and then have your urls.py point to instances.
    New (Django 1.3?) generic views are class-based.
    21
    votes

    Instead of usingrender_to_response to bind your context to a template and render it (which is what the Django docs usually show) use the generic viewdirect_to_template. It does the same thing thatrender_to_response does but it also automatically adds RequestContext to the template context, implicitly allowing context processors to be used. You can do this manually usingrender_to_response, but why bother? It's just another step to remember and another LOC. Besides making use of context processors, having RequestContext in your template allows you to do things like:

    <a href="{{MEDIA_URL}}images/frog.jpg">A frog</a>

    which is very useful. In fact, +1 on generic views in general. The Django docs mostly show them as shortcuts for not even having a views.py file for simple apps, but you can also use them inside your own view functions:

    from django.views.generic import simpledef article_detail(request, slug=None):    article = get_object_or_404(Article, slug=slug)    return simple.direct_to_template(request,         template="articles/article_detail.html",        extra_context={'article': article}    )
    community wiki

    2 Comments

    Save even more LOC by using the @render_to decorator available in django-annoying.bitbucket.org/offline/django-annoying
    ..or use newrender shortcut method from Django 1.3 (docs.djangoproject.com/en/dev/topics/http/shortcuts/#render)
    20
    votes

    I don't have enough reputation to reply to the comment in question, but it's important to note that if you're going to useJinja, it does NOT support the '-' character in template block names, while Django does. This caused me a lot of problems and wasted time trying to track down the very obscure error message it generated.

    Peter Mortensen's user avatar
    Peter Mortensen
    31.4k22 gold badges110 silver badges134 bronze badges
    answeredJun 19, 2009 at 16:35
    user61000's user avatar

    1 Comment

    One note that may or may not be applicable to "obscure error messages from jinja". Make sure to set TEMPLATE_DEBUG = False in settings.py. For some reason this will give you meaningful errors from Jinja templates.
    19
    votes

    Thewebdesign app is very useful when starting to design your website. Once imported, you can add this to generate sample text:

    {% load webdesign %}{% lorem 5 p %}
    answeredJun 2, 2009 at 23:32
    Roxy Light's user avatar

    1 Comment

    FYI, for anyone using Jinja2 instead of Django templates, you can do: {{ lipsum(5) }}
    19
    votes

    django.db.models.get_model does allow you to retrieve a model without importing it.

    James shows how handy it can be:"Django tips: Write better template tags — Iteration 4 ".

    Peter Mortensen's user avatar
    Peter Mortensen
    31.4k22 gold badges110 silver badges134 bronze badges
    answeredMay 14, 2009 at 18:19
    vikingosegundo's user avatar

    1 Comment

    Nice :O! And here I was doing lazy imports whenever I had circular dependencies.
    19
    votes

    Everybody knows there is a development server you can run with "manage.py runserver", but did you know that there is a development view for serving static files (CSS / JS / IMG) as well ?

    Newcomers are always puzzled because Django doesn't come with any way to serve static files. This is because the dev team think it is the job for a real life Web server.

    But when developing, you may not want to set up Apache + mod_wisgi, it's heavy. Then you can just add the following to urls.py:

    (r'^site_media/(?P<path>.*)$', 'django.views.static.serve',        {'document_root': '/path/to/media'}),

    Your CSS / JS / IMG will be available at www.yoursite.com/site_media/.

    Of course, don't use it in a production environment.

    community wiki

    1 Comment

    I use this in dev mode, and just to make sure I don't forget to turn this off in production, I wrap that URL rule in a DEBUG only conditional.
    18
    votes

    I learned this one from the documentation for thesorl-thumbnails app. You can use the "as" keyword in template tags to use the results of the call elsewhere in your template.

    For example:

    {% url image-processor uid as img_src %}<img src="{% thumbnail img_src 100x100 %}"/>

    This is mentioned in passing in the Django templatetag documentation, but in reference to loops only. They don't call out that you can use this elsewhere (anywhere?) as well.

    1 Comment

    If a keyword as "as" can be used with a template-tag depends of this particular tag. It is not defined by django itself but by single tags, depending on their meaning. Have a look in the mentioned url-tag to see how "as" is used:code.djangoproject.com/browser/django/trunk/django/template/…
    16
    votes

    django.views.generic.list_detail.object_list -- It provides all the logic & template variables for pagination (one of those I've-written-that-a-thousand-times-now drudgeries).Wrapping it allows for any logic you need. This gem has saved me many hours of debugging off-by-one errors in my "Search Results" pages and makes the view code cleaner in the process.

    answeredFeb 18, 2009 at 6:44
    jds's user avatar

    1 Comment

    You can find the new version of the book's chapter on Generic Views ondjangobook.com/en/2.0/chapter11 . The one on the comment goes to the Django pre-1.0 version of the book (Django book 1.0)
    16
    votes

    PyCharm IDE is a nice environment to code and especially debug, with built-in support for Django.

    community wiki

    Comments

    14
    votes

    Usexml_models to create Django models that use an XML REST API backend (instead of a SQL one). This is very useful especially when modelling third party APIs - you get all the same QuerySet syntax that you're used to. You can install it from PyPI.

    XML from an API:

    <profile id=4>    <email>[email protected]</email>    <first_name>Joe</first_name>    <last_name>Example</last_name>    <date_of_birth>1975-05-15</date_of_birth></profile>

    And now in python:

    class Profile(xml_models.Model):    user_id = xml_models.IntField(xpath='/profile/@id')    email = xml_models.CharField(xpath='/profile/email')    first = xml_models.CharField(xpath='/profile/first_name')    last = xml_models.CharField(xpath='/profile/last_name')    birthday = xml_models.DateField(xpath='/profile/date_of_birth')    finders = {        (user_id,):  settings.API_URL +'/api/v1/profile/userid/%s',        (email,):  settings.API_URL +'/api/v1/profile/email/%s',    }profile = Profile.objects.get(user_id=4)print profile.email# would print '[email protected]'

    It can also handle relationships and collections. We use it every day in heavily used production code, so even though it's beta it's very usable. It also has a good set of stubs that you can use in your tests.

    (Disclaimer: while I'm not the author of this library, I am now a committer, having made a few minor commits)

    1 Comment

    interesting project, keep it up!
    14
    votes

    Use database migrations. UseSouth.

    community wiki

    Comments

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.