Testing Django 1.7 RC2 in less than a minute

Why should I care about 1.7 RC2

Django | Now Migrating

A couple of days ago, the second release candidate for Django 1.7 was released - blog post on the Django blog here. These are great news for the Django community, as new awesome features are becoming available through the 1.7 release and are included in this release candidate. Some of these features are the ones below:

  • Built-in schema-migration framework
  • Improved tools for validating and checking your projects
  • A complete refactor of the way Django identifies and loads your applications
  • Support for custom database lookups.

For a complete feature list, visit this link.

You can either wait for 1.7 to move to production, or you can simply go to the downloads page and grab the release candidate.

Trying out 1.7 RC2 will be fun, since you will be experimenting with the new features coming out shortly, but is also really important for the development of the project. By testing the new features and the framework as a whole, you are helping in finding and identifying bugs before the production release.

In this tutorial, you'll learn how to set up an isolated Django 1.7 RC2 environment in less than a minute in SourceLair and how to use the new schema migrations and application loading features.

Enough said, demo time!

Preparing the environment for testing 1.7 RC2

In order to prepare your environment for 1.7 RC2, you can use either a completely new VM or virtualenv so that the new installation does not interfere with your existing projects.
If you want to avoid doing so though, SourceLair comes to the rescue!

By using SourceLair, you will instantly avoid interfering with your existing projects, since each SourceLair project lives in each own, completely isolated environment. 1.7 RC2 is not yet supported, as we only support production releases, but SourceLair supports a fully featured terminal with pip pre-installed, you'll be able to setup our environment for 1.7 in no time. Here are the steps to install Django 1.7 RC2:

  1. Create a new Project in SourceLair, name it django-testing and select Django version 1.6 (the Django version does not matter, since we'll install our own version using pip).
  2. Delete the django_testing directory that was automatically created.
  3. In the Linux Terminal at the bottom, type
    pip install https://www.djangoproject.com/download/1.7c2/tarball/
  4. Create a new Django project, using the Terminal, by typing
    django-admin startproject django_testing
  5. Close the terminal to let the File Explorer sync

Done! Now you have set up your environment and after starting the Django server, you have a public URL to view changes in real time, as you make them.

You can easily access the most common Django commands like shell, syncdb or runserver, by using the Command Palette (Ctrl/Cmd + Shift + P) and typing "Django". The list will be automatically filtered with the Django related commands.
If you need to use other, more complicated commands like the ones introduced in 1.7, you can do so using the Terminal as you would do in your VM.

Testing some of the new features

First of, let's start the server and see if everything is working fine. Start the server, either using the Command Palette or the button below the file explorer and then press the View button. This will open your project's public URL, where you will be able to access your server and see your changes in real time. You can also see the server logs in the Server Logs tab.

Schema migrations

Let's start experimenting with the new Scema migrations. To do so, let's create our database. In SourceLair, the directory used for persistent data is /mnt/data, so you'll have to place your database there. Let's go and change the BASE_DIR value to '/mnt/data' in settings.py. Then, either use the syncdb command in the Command Palette, or cd django_testing and type the new python manage.py migrate command in the Terminal to create the base database. To open the Terminal again, simply open the Command Palette and type "Terminal".

To test this feature, let's start by creating a simple app.
Create a new Django app, using the "Start" App command of Command Palette and name it "polls". Then, in the models.py of the new app, add the following code.

# django_testing/polls/models.py

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

Add the "polls" app in the INSTALLED_APPS list in settings.py and type python manage.py makemigrations polls in the terminal to create the migrations of the models. The first migration is the actual creation of the models, so now move on and type python manage.py migrate to apply them.

Hooray! That was damn easy and so will be any other migrations you'll make later on when the database schema changes. For example, let's make a minor change in the Choice model above and add a last_vote field.

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    last_vote = models.DateTimeField('last vote date')

After that, go and type python manage.py makemigrations polls like before in the Terminal. As you can see, you can add a default value - in our case datetime.datetime.now() would be perfectly fine - and move on without a hassle. Finally, type python manage.py migrate to migrate the new change.

Application loading

A big pain when creating Django Web apps is deciding where to put initialization code that needs to be executed once and only once. The most common example is declaring signals for an application. There are great and big conversations throughout the internets on the most preferable way to declare signals, with the most supported ways being either importing the signals in the models.py or importing them in the __init__.py of each application.

Both ways have their pros and cons, but fortunately the newest loading mechanism of applications introduces a better solution. The related feature announcement is very descriptive, so let's move straight ahead to the demo!

In the "polls" app we have created before, let's add a signals.py file. We will store the database entry for the current votes in a secret field _db_votes after the initializing a new model and then compare this to the current value before saving, so that we can update the latest last_vote field if needed.

# /django_testing/polls/signals.py

import datetime

def choice_post_init(sender, instance, **kwargs):
    setattr(instance, '_votes', instance.votes)

def choice_pre_save(sender, instance, **kwargs):
    if hasattr(instance, '_votes'):
        if instance.votes > getattr(instance, '_votes'):
            instance.last_vote = datetime.datetime.now()

Then, the last thing to do is create an AppConfig for our "polls" app and connect to the Django signals there. The AppConfig can be placed in apps.py and will look like the one below.

# django_testing/polls/apps.py

from django.apps import AppConfig
from django.db.models.signals import post_init
from django.db.models.signals import pre_save

from polls import signals
from polls.models import Choice

class PollsAppConfig(AppConfig):
    name = 'polls'
    verbose_name = 'Polls'

    def ready(self):
        post_init.connect(signals.choice_post_init, sender=Choice)
        pre_save.connect(signals.choice_pre_save, sender=Choice)

Last thing to do is change the record in INSTALLED_APPS from polls to polls.apps.PollsAppConfig and everything is set.

That's all for now, you can either play with any feature you'd like, or continue with the awesome Tutorial Series and the new applications documentation from Django!

Where you can get

Updates and contact us

You can check out product updates at the SourceLair blog, or learn more about us at State of Progress, where we share our thoughts on software development and management.

Stay in touch

You can reach out to us at Twitter, Facebook, Instagram or email us at [email protected].