Category Archives: Django

Content types and Django CMS

Screenshot of the new ENB website

The new ENB website

One of our latest projects to go live is a new website for the English National Ballet. Part of a major rebrand, we completely replaced their old PHP site with a new content-managed site powered by Django CMS.

Django CMS is very flexible, largely due to its minimalistic approach. It provides no page templates out of the box, so you can construct your HTML from the ground up. This is great if you want to make a CMS with a really strong design, because there is very little interference from the framework. However, its minimalistic approach also means that you sometimes have to write extra code to tie all the content together.

A good example of this is content types. In Django CMS, there is only one content type: Page. It has certain fields associated with it e.g. title, slug, published. Any other information that appears on a page comes courtesy of plugins. The default Django CMS plugins give you everything you need to add arbitrary text, images and video to a page. But what if you want more fields for your page? Let’s say, for example, you are representing a ballet production and you want category, thumbnail and summary text fields, which don’t appear on the page itself but are needed for listings elsewhere on the site?

We decided to create a special “metadata” plugin to be added to the production pages, that would only be visible to content editors and not end users. This was seen as the best solution that achieved our goal while maintaining a decent user experience for the editors.

The plugin model looks something like this:

class ProductionDetails(CMSPlugin):
    summary = models.CharField(max_length=200) # Short summary, shown in listings
    image = FilerImageField() # Thumbnail image, shown in listings
    audiences = models.ManyToManyField(Audience) # Categorisation

Note the use of django-filer for the image field. This is simply the best add-on I have encountered for dealing with image uploads and the inevitable cropping and resizing of said images. You can also use cmsplugin-filer (by the same author) to replace the standard image plugin that comes with Django CMS.

Now querying the database for, say, the first 10 productions for a family audience (audience id 3) is as simple as:

ProductionDetails.objects.filter(audiences=3, placeholder__page__published=True)[:10]

So now we have a plugin model that we can query, and we don’t need a template as we don’t want it to appear on the actual page, right? Wrong. We still want to provide a good user experience for the editors, and this includes looking at a page in edit mode and being able to tell whether the page already has the plugin or not. So we use request.toolbar.edit_mode in the template to decide whether to render the plugin:

{% load thumbnail %}

{% if request.toolbar.edit_mode %}
<div id="production-details">
 <img src="{% thumbnail instance.image 100x100 crop upscale subject_location=instance.image.subject_location %}" />
 <p>Summary: {{ instance.summary }}</p>
 <p>Audiences: {{ instance.audiences.all|join:', ' }}</p>
</div>
{% endif %}

Now this information will only appear if an editor has activated the inline editing mode while looking at the page. If they look at the page and the information is missing, they know they need to add the plugin!

This solution works quite well for us, although it is still fairly easy to create a page and forget to give it any metadata. Ideally it would be mandatory to add a metadata plugin. Perhaps the subject of a future blog post!

Running a Django (or any other) dev instance over HTTPS

Being able to run your dev instance over HTTPS is really useful: you might spot some weird bug that would have bitten you in production, and if you do find one, you can debug it much more easily. Googling for this subject resulted in several different tutorials using stunnel, but all of them broke in some way on my machine running Ubuntu Maverick. So here is how I got stunnel working – perhaps it will help someone else too:

sudo aptitude install stunnel
sudo su -
cd /etc
mkdir stunnel
cd stunnel
openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.pem
openssl gendh 2048 >> stunnel.pem
chmod 600 stunnel.pem
logout
cd

Now create a file called dev_https with the following text:

pid=
foreground=yes
debug = 7

[https]
accept=8443
connect=8000
TIMEOUTclose=1

Note: this assumes your web server is running on port 8000. If it’s not, change the value of “connect” to the appropriate port.

Finally, run:

sudo stunnel4 dev_https

Now if you go to https://localhost:8443/, you should see your HTTPS-enabled dev instance!

Note: To properly simulate a HTTPS connection in Django, you should also set an environment variable HTTPS=on. Without this, request.is_secure() will return False. You could set it at the same time as starting your dev instance e.g:

HTTPS=on python manage.py runserver

 

Scaffolding template tags for Django forms

We love Django here at Isotoma, and we love using Django’s awesome form classes to generate self-generating, self-validating, [X]HTML forms.

However, in practically every new Django project I find myself doing the same thing over and over again (and I know others do too): breaking the display of a Django form instance up into individual fields, with appropriate mark-up wrappers.

Effectively I keep recreating the output of BaseForm.as_p/as_ul/as_table with template tags and mark-up.

For example, outputting a login form, rather than doing:

{{ form.as_p }}

We would do:

<p>
{% if form.username.errors %}
  {% for error in form.username.errors %}
    {{ error }}
  {% endfor %}
{% endif %}
{{ form.username.label }} {{ form.username }}
</p>
<p>
{% if form.password.errors %}
  {% for error in form.password.errors %}
    {{ error }}
  {% endfor %}
{% endif %}
{{ form.password.label }} {{ form.password }}
</p>

Why would you want to do this? There are several reasons, but generally it’s to apply custom mark-up to a particular element (notice I said mark-up, not styling, that can be done with the generated field IDs), as well as completely customising the output of the form (using <div>‘s instead etc.), and also because some designers tend to prefer this way of looking at a template.

“But”, you might say, “Django already creates all this for us with the handy as_p/as_ul/as_table methods, can you just take the ouput from that?”
Well, yes, in fact on a project a couple of weeks ago that’s exactly what I did, outputting as_p in a template, and then editing the source chucked out in a browser.
Which gave me the idea to create a simple little tool to do this for me, but with the Django template tags for dynamically outputting the field labels and fields themselves.

I created django-form-scaffold to do just this, and now I can do this from a Python shell:

>>> from dfs import scaffold
>>> from MyProject.MyApp.forms import MyForm
>>> form = MyForm()
>>> # We can pass either an instance of our form class
>>> # or the class itself, but better to pass an instance.
>>> print scaffold.as_p(form)

{% if form.email.errors %}{% for error in form.email.errors %}
{{ error }}{% endfor %}{% endif %}
<p>{{ form.email.label }} {{ form.email }}</p>
{% if form.password1.errors %}{% for error in form.password1.errors %}
{{ error }}{% endfor %}{% endif %}
<p&gtl{{ form.password1.label }} {{ form.password1 }}</p>
{% if form.password2.errors %}{% for error in form.password2.errors %}
{{ error }}{% endfor %}{% endif %}
<p>{{ form.password2.label }} {{ form.password2 }}</p>

Copy and paste this into a template, tweak, and Robert’s your mother’s brother.

As well as as_p(), the dfs.scaffold module also has the equivalent functions as_ul(), as_table, and an extra as_div() function.

Returning an actual proper real life HTTP code from a Django error page

Go to a non existent page on a Django site and you will (hopefully) be met with a friendly error page telling you not to panic, everything is OK and all you’ve done is mistyped the URL or something.

If it’s your thing, you may be interested enough to look see what the actual HTTP code for the page is in the header; chances are that it will be a 200 rather than a 404 as the default handler just passes the dealings onto the HttpResponse class.

Generally speaking this is fine, but there are situations where an accurate code would be very handy, as I found out the other day when I was trying to detect whether a file had been uploaded to a remote server. Scraping the resultant HTML for “Page not found” is not my idea of a robust solution.

So, instead, pass the error page’s HTML into the respective class by putting something like this in urls.py:


handler404 = 'urls.return_404'
handler500 = 'urls.return_500'

def return_404(request):
	return HttpResponseNotFound(
                render_to_string("errors/404.html"))

def return_500(request):
	return HttpResponseServerError(
                render_to_string("errors/500.html"))

Fullest of props to PiotrLegnica at Stack Overflow for this most elegant of solutions.

Edit: After further examination (see the comments) the default handlers do act as expected, but you’re still restricted to where you put your error templates, i.e. the root of the templates directory.
To my mind, it’s neater if you can specify a dedicated location.

Getting the name of the current view in a Django template

Recently I have been working with generalised/reusable Django base templates, and I had the need to know the name of the current view using the template.
As it turns out, there currently aren’t any simple methods of doing this out there, and some of the nicer ones at their best make use of monkey patching.

After some playing around I found the cleanest, and quite simple, way is to use a custom template context processor.
A context processor provides extra values to bind to a template instance (it’s context; similar to including items in the data dict when calling render_to_response()).

By using a custom context processor we can assign a ‘current_view’ value to the template context, containing the namespaced name of the current view.
That just leaves one problem: how do we find the current view from within the request context.
inspect to the rescue!

Update: see Alexander Dutton’s comment for the even cleaner way by using middleware instead of stack inspection.

With inspect.stack() and inspect.getmodule() we can both grab the a stack of frames (e.g. the execution frames up to and including the current execution frame, which should be our context processor instance), and the module the frame is in.

from inspect import stack, getmodule

def ContextWithView(request):
    """Template context with current_view value,
    a string with the full namespaced django view in use.
    """
    # Frame 0 is the current frame
    # So assuming normal usage the frame of the view
    # calling this processor should be Frame 1
    name = getmodule(stack()[1][0]).__name__
    return {
        'current_view': "%s.%s" % (name, stack()[1][3]),
    }

To use this in a view, just import it and then pass it as the context in your render_to_response() call:

"""main/my_site/views/misc.py - misc views"""

from main.my_site.context_processors import ContextWithView

def my_view(request):
    # Do some stuff
    return render_to_response(
        'my_template.html',
        {},
        context_instance=ContextWithView(request)
    )

From within a template you can then use current_view, which for the above should output something like “main.my_site.views.misc.my_view”

Misc.

If you’re using RequestContext with your templates to make sure request, user etc. are always available in your templates, you can chain context processor calls like so:

from inspect import stack, getmodule
from django.template import RequestContext

def ContextWithView(request):
    """Template context with current_view value,
    a string with the full namespaced django view in use.
    """
    d = RequestContext(request)
    # Frame 0 is the current frame
    # So assuming normal usage the frame of the view
    # calling this processor should be Frame 1
    name = getmodule(stack()[1][0]).__name__
    d['current_view'] = "%s.%s" % (name, stack()[1][3])
    return d

If, like me, you then need to render a reverse URL using the ‘current_view’ variable, you’ll find the the {% url %} tag in Django only works on static strings, and not variables, so we need to make a custom tag to do this for us:

"""main/my_site/templatetags/extras.py
"""

from django.core.urlresolvers import reverse
from django import template

register = template.Library()

@register.simple_tag
def var_url(view, *args, **kwargs):
    return reverse(view, args=args, kwargs=kwargs)

{% comment %}
To use {% var_url %} in your template
just import and use as you would {% url %}
{% endcomment %}

{% load extras %}

{% block content %}
The URL for this view is <em>{% var_url current_view %}</em>.
{% endblock content %}

Uniquifying Delicious Links

We use delicious a lot here at isotoma, but given that we’re all likely to mostly bookmark the same links, we thought it’d be cool to filter the stream for a single copy of each link.

Click here

This site should pull all the streams for the entered users over the last number of days and give you all the links that were posted in the last number of days (or 100 items, whichever is smaller).

I hope it’s of use.

Debugging django unit tests with WING IDE

Wing is a nice IDE, it does autocompletion, project management and other fancy stuff like SVN integration.

There is a page here on how to set up Wing so that it’ll debug within a django environment, including how to make it work with the auto reloading feature, however this will not help if you wish to debug within unit tests, which can be extremely useful, particuarly if you are following TDD or test-first philosophies.

The answer to this:

  1. Set the manage.py of your django project to be the ‘Main Debug File’. Do this by finding manage.py in the Project View and right clicking on it. The option is about half way down the drop down.
  2. Set the environment variables required in the Project settings.
  3. Right click the manage.py again and go to “File Properties”
  4. In the Debug tab of File Properties, set the ‘Run Arguments’ to ‘test’ (without the quotes)
  5. Add a breakpoint somewhere in your tests
  6. Press Debug
  7. Marvel.

Hope this helps someone, I’ve just spent time getting it working, only to blast my .wpr file and have to remember how to do it again, so I thought I’d write it down.