Ghosts of Python Past
3.5.3 Applying Migrations to Create or Modify a Database The command to run the code in the migrations files, colloquially called applying a
migration, ismigrate. If you’ve been following closely, you already used the command in Chapter 1, before we used therunservercommand. Calling the command created a default SQLite database, which Django requires to run on a server.
Regardless of whether you already have a database, you will now callmigrateagain, as in Example 3.33.
Example 3.33:Shell Code
$ ./manage.py migrate
If you don’t already have a database, Django will create one nameddb.sqlite3, as
specified on line 64 of/suorganizer/settings.py. Django will also produce the
output shown in Example 3.34. Example 3.34:Shell Code Operations to perform:
Synchronize unmigrated apps: messages, staticfiles
Apply all migrations: blog, auth, admin, organizer, sessions, contenttypes
Synchronizing apps without migrations: Creating tables...
Running deferred SQL... Installing custom SQL... Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying organizer.0001_initial... OK Applying blog.0001_initial... OK Applying sessions.0001_initial... OK
54 Chapter 3 Programming Django Models and Creating a SQLite Database
If you already have a database, Django will modify your database to account for the changes outlined in the migration files we just generated. Instead of the text in Example 3.34, Django will output a subset, as it is doing a subset of the work (Example 3.35).
Example 3.35:Shell Code Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: organizer, sessions, blog, auth, admin, contenttypes
Synchronizing apps without migrations: Creating tables...
Running deferred SQL... Installing custom SQL... Running migrations:
Rendering model states... DONE
Applying organizer.0001_initial... OK Applying blog.0001_initial... OK
In either case, your database is identical in structure, which is the purpose of migrations. If you’re curious about what, exactly, Django is telling the database to do, you can use thesqlmigratecommand to ask Django. For instance, the command./manage.py sqlmigrate blog 0001asks Django for the SQL code it uses when applying the first migration of the blog app. The result is printed in Example 3.36.
Example 3.36:SQL Code BEGIN;
CREATE TABLE "blog_post" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(63) NOT NULL,
"slug" varchar(63) NOT NULL,
"text" text NOT NULL,
"pub_date" date NOT NULL); CREATE TABLE "blog_post_startups" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"post_id" integer NOT NULL
REFERENCES "blog_post" ("id"),
"startup_id" integer NOT NULL
REFERENCES "organizer_startup" ("id"), UNIQUE ("post_id", "startup_id"));
CREATE TABLE "blog_post_tags" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"post_id" integer NOT NULL
REFERENCES "blog_post" ("id"),
"tag_id" integer NOT NULL
REFERENCES "organizer_tag" ("id"), UNIQUE ("post_id", "tag_id"));
CREATE INDEX "blog_post_2dbcba41" ON "blog_post" ("slug"); CREATE INDEX "blog_post_startups_f3aa1999"
3.5 Using Django to Automatically Create a SQLite Database with manage.py 55
CREATE INDEX "blog_post_startups_99f77c8c" ON "blog_post_startups" ("startup_id"); CREATE INDEX "blog_post_tags_f3aa1999"
ON "blog_post_tags" ("post_id"); CREATE INDEX "blog_post_tags_76f094bc"
ON "blog_post_tags" ("tag_id"); COMMIT;
TheCreateModeloperation in the blog migration file we generated results in all of the SQL code listed in Example 3.36. When we invokemigrate, Django uses the data in the instance ofCreateModelto generate this SQL, which it then applies to the database. The creation of theblog posttable is thus expected. Take note again of theidprimary key, automatically created for us but not specified in our models. A little more tricky is the creation of theblog post startupsandblog post tagstables, which are the result of the many-to-many field seen in both our models and the migration file. Finally, Django creates indexes to allow rapid access to all of the keys, both primary and related.
The key takeaway from all of this is that models allow Django to automatically create and modify databases thanks to migrations. Django is quite intelligent about this process and focuses on shortening code. Django automatically supplies a primary key to models and sets up indexes for these keys. Furthermore, Django allows us to avoid the tedious and repetitive process of defining many-to-many relations as full tables and instead provides a field to shorten our code and the process.
Info
One of the most common questions on the Internet with relation to Django’s many-to-many relations is, How do I customize or add information to the relation? For instance, given a many-to-many relation between hotel rooms and guest, how would one store the reservation number for each relation? The answer is that Django allows developers to create their own models for relations. To use the model (replacing Django’s generated table), use thethroughparameter when instantiating a
ManyToManyField. This is Django’s recommended method and results in the same SQL as if you had manually built a many-to-many relationship using nothing but foreign keys (don’t do this—it’s a lot of extra work for nothing).
We are now in a position to start adding data to the website.
Ghosts of Django Past
Prior to Django 1.7, Django did not provide migrations natively. If you’re working with migrations in Django 1.6 or earlier, you are likely using an app called South. South does not work with Django 1.7 or later, and so we do not cover its use in this book. However, the principle is exactly the same.
If you’re working in Django 1.6 or earlier and you don’t have migrations, then you will be interested in thesyncdbandsqlallcommands. That said, I urge you to add South to your project. If you change your models without a migration system, you will be forced to edit your database manually or else to throw it out and regenerate it.
56 Chapter 3 Programming Django Models and Creating a SQLite Database