Perspective Unspoken

My perspective on Git, Docker, Python, Django, PHP and other stuff

5 tips for serious Django apps

So if you’re working on a Django app that you plan to ever move to production, there are several things that you should take into consideration. Far too often optimization is an after-thought that gets built in eventually. Here a few simple tips that can be built in without too much work and can really increase database utilization.

Use values and values_list

The typical way to access stuff from the database is like this:

This isn’t an issue when you start off and your table probably only has a few columns. However, when your database grows, and you do your migrations, those same lines of code will slow down over time since the database is fetching more information as your table grows horizontally and vertically. An easy way to keep it constant (or more under control) is to use values or values_list to only fetch the columns that are needed. Here a few examples:

values_list gives a flattened list, while values will return a list of dictionaries.

Use prefetch_related and select_related for nested models

When ever you know you’re going to be accessing data on a child model for some model, you should use one of these functions to reduce the amount of lookups the database will have to do. See the example below:

This is great because sometimes our relationships get pretty nested and if you have any respect for Orders of Growth you’ll appreciate that whatever you can do to make the database cry less is well appreciated. Both functions cause Django to construct a more complex query that will select more information from the outset instead of going back to the database at each stage of the loop.

 

Use the iterator function for memory intensive DB calls

This is another simple thing that can be introduced for scenarios where you have to do processing on ALOT of data. When you use a QuerySet in Django, typically it will be cached so that subsequent calls to the QuerySet doesn’t require additional trips to the database. That’s great in most cases but for some, where you have huge amounts of database to process you may not want to do that at all. The iterator function essentially eliminates the caching that the QuerySet typically offers which means more trips to the database but less hogging of memory.

 

Abuse Class Base Views

Generic Class Based Views are a great step forward from functional views. It really allows you to get to the more complex stuff and get boilerplate stuff out of the way. Additionally, as your site grows, you’ll find that there are many instances you may end up repeating yourself. For repetition, there’s a beautiful solution called inheritance. Instead of copying a function based views and all the decorators you applied to it to a new function you need, you can instead just subclass the class based views you wrote and adjust it to inject the extra logic you need. Here are a couple quick examples:

  • Template View – great if you just need to render a page with a few items stuffed in the context.

  • Redirect View – if you just need to, as it suggests… redirect to somewhere.

  • Detail View – great if you’re showing an object based on some “pk” that’s in the url.

  • Form View – have a form that you need to have someone submit, have it validated, show errors if any and then redirect on success.

Just mentioned a couple that I use heavily these days. There are countless generic views that can be used to make your job easier. Also, each generic view typically consists of several mixins that can be used to make up your concoctions. Classy Class Based Views (ccbv.co.uk) is a great site I use regularly to remind myself of what the makeup of each CBV looks like. It has documentation for 1.3 – 1.9.

 

Use template context processors and template tags

This is another must for serious sites. I’d go as far as to say it’s mandatory for elegance and keeping yourself inline with DRY principles. Both significantly aid the process of re-using templates and general functionality.

Context processors allow you to add variables and data you use regularly on the site to the request context that’s passed to templates. They are great for adding general settings you need to be accessible everywhere. Django doesn’t put “settings” in templates by default, but you can selectively add whatever settings you need to context processors. For example, for one project we added things like the site name and debug mode. It’s great for storing metadata about your site. More importantly, as you add different applications to your project, you can put application specific information in the context processor. I did an e-commerce project that stored shopping cart information in the context processor. They’re also extremely easy to build:

Template tags are great for abstracting pockets of functionality away into reusable libraries of code. If there’s a specific way that a particular model is displayed, for e.g. a product, you could abstract that into a template tag. I used template tags recently in a project at work to abstract a complex Django model and was able to encapsulate it’s creation, modification and deletion, all by using a simple template tag. You can use them for practically any bit of functionality you need to reuse on the site, be it search, model display, pagination or anything else you come up with.

 

Bonus Tip

As a bonus, and this is probably a combined tip anyway… but… don’t use objects.all unless you’re completely certain about it. When you’re just starting your website, objects.all may mean pulling 20, 50 or say even 500 objects into memory depending on what model you’re working on. However, as that site grows in production, that line of code is guaranteed to be a bottleneck for your code if the table grows significantly. In production under heavy use, it could mean trying to pull 20k, or 100k results into memory. You should really try and stick the filter function in there somewhere to ensure that you’re cutting down the results vertically, or and use values to cut down the results horizontally.

Djangooptimizationtips

jaywhy13 • December 13, 2015


Previous Post

Next Post

www.000webhost.com