Let’s learn by example. And let's use, for example, the Django Tutorial 1.
Create Your Project
Following the example, create a new project:
django-admin.py startproject mysite
mysite/ and edit your new
settings.py to adjust your database settings, and add migratory to your INSTALLED_APPS, for instance:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.migratory', # Migratory )
When you're ready, do a
python manage.py syncdb to setup the base tables.
Create the polls app:
python manage.py startapp polls
polls/models.py to match the django tutorial:
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 = models.CharField(max_length=200) votes = models.IntegerField()
And then edit your
settings.py again to add the new app:
INSTALLED_APPS = ( ... 'django.contrib.migratory', 'mysite.polls' )
And now finally, perform a syncdb:
python manage.py syncdb
Create Some Data
Following the Django Tutorial, create a poll in the shell:
python manage.py shell
>>> from mysite.polls.models import Poll, Choice >>> import datetime # Create a poll >>> p = Poll(question="What's up?", pub_date=datetime.datetime.now()) >>> p.save() # Add some choices >>> p.choice_set.create(choice='Not much', votes=0) >>> p.choice_set.create(choice='The sky', votes=0) # Add your vote >>> c = p.choice_set.get(choice='The sky') >>> c.votes = 1 >>> c.save()
Now, if you want to add the extra
was_published_today() go ahead, it's not really important for this tutorial.
Okay, so this is where it gets interesting.
We created some data, but now we realize that we need to be able to turn on and off seperate polls. We need to add an "enabled" field. Okay, no problem:
from django.db import models class Poll(models.Model): question = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') enabled = models.BooleanField(default=True) # New Field class Choice(models.Model): poll = models.ForeignKey(Poll) choice = models.CharField(max_length=200) votes = models.IntegerField()
Now we have to reflect the changes in our database. To do so, we create a migration:
> python manage.py migrate polls add-enabled-on-polls
Let's break it down:
- python manage.py
- The usual manage.py start.
- Create a new migration.
- The app we want to create the migration for.
- A slug for our migration used as an identifier.
We then see an overview of what's going on:
Adding '2008-12-30-add-enabled-on-polls.py' to manifest... Writing migration to: ../mysite/polls/migrations/2008-12-30-add-enabled-on-polls.py Writing snapshot to: ../mysite/polls/migrations/2008-12-30-add-enabled-on-polls.snap Changes to the model 'Poll': Add the new field 'enabled'. Please look over the changes. When you feel confident they are correct, issue a 'syncdb': > python manage.py syncdb
It tells us that it added a new migration script named '2008-12-30-add-enabled-on-polls.py', although the date will be changed for you. Where is the script? Well the app layout will now look like this:
polls/ __init__.py migrations/ 2008-12-30-add-enabled-on-polls.py 2008-12-30-add-enabled-on-polls.snap __manifest__.py models.py views.py
You can see it also created the file
2008-12-30-add-enabled-on-polls.snap, which is a snapshot of our current models for reference, and is important in executing the migration later on.
In addition, it tells us that it added the script to the manifest, which is the newly created
__manifest__.py in the
migrations/ folder. This file lists, in order, each migration script, it looks like:
[ '2008-12-30-add-enabled-on-polls.py', ]
The output also gives us a description of everything that the migration will do:
Changes to the model 'Poll': Add the new field 'enabled'.
Ah, correct! We want to add the new field 'enabled', exactly. Let's look at what the script actually does:
""" Django Migration 2008-12-30-add-enabled-on-polls.py """ def up(database): database.add_field('Poll', 'enabled')
Pretty simple, the migration defines an
up() function that takes a Database Manager as its one and only argument. The database manager allows you to adjust the database and, in between adjustments, use the models as normal with the Django ORM.
Well, that looks perfectly good to me, so let's execute it:
python setup.py syncdb
And we're done, our database should now represent our models.py quite well.
>>> from mysite.polls.models import Poll, Choice >>> p = Poll.objects.get() >>> p.question u"What's up?" >>> p.enabled True