Models and Migrations

(Comments)

Setting up Database

Before we start with models let's understand how to setup database to work with Django. Django comes pre bundled and ready to work with SQLite database, which for development and for very small lightweight websites would be enough to wor with, but if the scale of the website or the user-base of the website is even moderately high, SQLite is definitely not enough.


Other than SQLite Django can work with the following Databases:
    • MySQL
    • Postgres
    • Oracle


Let's see how to setup the database for each of the above backends.



SQLite

The settings for any database is registered in the settings.py file in myprojectname/myprojectname/ directory. We register them by listing the settings for the database as a Python dictionary. It is a nested dictionary whose contents map a database alias to a dictionary containing the options for an individual database.


For the SQLite backend we have the following setting, which is probably the simplest:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'awesomedb',
    }
}


Please note that the dictionary is assigned to a variable named DATABASES. It should be named the same. Also the 'NAME' property specifies the SQLite database filename that should be used to store the backend data.



MySQL, Postgres, Oracle

When connecting to other database backends, such as MySQL, Oracle, or PostgreSQL, additional connection parameters will be required, viz, database username and password, database host URL and port etc.


Also unlike SQLite database, we need to install certain dependencies for Django to be able to connect to these backends.
    • If you’re using PostgreSQL, you’ll need the psycopg2 package (2.5.4 or higher).
    • If you’re using MySQL, you’ll need a DB API driver like mysqlclient. Also MySQL version should be 5.5 or higher.     • If you’re using Oracle (v11.2 or higher supported), you’ll need a copy of cx_Oracle (version 5.2 or higher).


Given below is the example for connecting a PostGres:


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'awesomedb',
        'USER': 'awesomedbuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}


For connecting to other Databases, edit the value for 'ENGINE' as follows:


Database 'ENGINE' value
MySQL 'django.db.backends.mysql'
ORACLE 'django.db.backends.oracle'


Timezone Setting

While you are setting up the myprojectname/settings.py, set TIME_ZONE to your timezone. TIME_ZONE should be a string representing the time zone. Click here for the list of timezones.



Installed apps

Note the 'INSTALLED_APPS' setting at the top of the file. This holds the names of all the Django applications activated in this particular Django project. As we have discussed above, apps can be used in multiple projects and can also be packaged and distributed for use by others in their projects.


The default 'INSTALLED_APPS' contain the following apps. These apps are prepackaged apps that come with Django.
    • django.contrib.admin -> The admin site. We will look in to it ahead in this blog.
    • django.contrib.auth -> The authentication system for Django.
    • django.contrib.contenttypes -> A framework for content types.
    • django.contrib.sessions -> The sessions framework.
    • django.contrib.staticfiles -> Framework for managing static assets files.


Important Note: Some of the above applications make use of database. And right now although you may have setup the SQL server (no setting up needed for SQLite.), the database tables needed for these applications aren't migrated into them. So lets migrate them first. To do that, run the following command:



python manage.py migrate



Creating a Model

Models are nothing but database layouts with additional metadata. Let's see how to create our first Models in Django.


In our simple poll app, we’ll create two models: Question and Choice. A Question has a question and a publication date. A Choice has two fields: the text of the choice and a vote tally. Each Choice is associated with a Question.


These concepts are represented by simple Python classes. Edit the polls/models.py file so it looks like this:


# Python Code
# polls/models.py

from django.db import models


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


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)


Let's dissect this block of code and understand the significance of each line.


Both the models are represented by a class that has django.db.models.Model as its parent class. And the fields (or columns, in SQL terms) are represented by class variables.


For the fields that are supposed to be persisted are represented by an instance of a subclass of the Field class - e.g., CharField for character fields, DataTimeField fot datetimes and IntegerField for integer fields and so on.


The name of each Field instance (e.g. question_text or pub_date) is the field’s name, in machine-friendly format. You’ll use this value in your Python code, and your database will use it as the column name.


Some Field classes have required arguments. CharField, for example, requires that you give it a max_length. That’s used not only in the database schema, but in validation, as we’ll soon see. They also have optional arguments; in our case we have set the default value of votes to 0.


Finally, note a relationship is defined, using ForeignKey. That tells Django each Choice is related to a single Question. Django supports all the common database relationships: many-to-one, many-to-many, and one-to-one.


Migrating the Models

Django apps are basically "pluggable" modules. So here we have given Django a lot of information with our models.py code. And based on this information Django Creates the database schema and a Python wrapper API around this database for accessing the data from the database.


But for all this to happen we need to tell our Django project that we want the polls app to be installed. And to do that we add a reference to its configuration class in the 'INSTALLED_APPS' setting we saw earlier. The PollsConfig class is in the polls/apps.py file, so its dotted path is 'polls.apps.PollsConfig'. Edit the mysite/settings.py file and add that dotted path to the INSTALLED_APPS setting. It’ll look like this:


# Python Code
# myprojectname/settings.py

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]


This tells Django to include the polls app. Now let's make the migration files:



python manage.py makemigrations polls


You should see something similar to the following:


Migrations for 'polls':
  polls/migrations/0001_initial.py:
    - Create model Choice
    - Create model Question
    - Add field question to choice


What this does is notify Django that certain changes have been made in the models. These changes are stored in a migration file. This migration file is used to change the database schema. These migrations are just regular files with instructions to change the schema. We could read the migration if needed. It will be a file similar to polls/migrations/0001_initial.py. Reading them is not a compulsion, rather it is just to quench your thirst of curiosity.


These migration files do not include actual SQL statements rather it includes a intermediate python code which is used to generate the SQL commands. To view the actual SQL statements we could run the following command:



python manage.py sqlmigrate polls 0001


Note that the 0001 denotes the prefix of 0001_initial.py


Let's actually write the changes to database now. This can be done by running the following command:



python manage.py migrate


This actually applies the changes into the database by running the migration. Django has a note of all applied migrations and runs them against the database only if not yet applied. Thus essentially syncing the changes to your database based on you your changes in Models.


The reason that there are separate commands to make and apply migrations is because you’ll commit migrations to your version control system and ship them with your app; they not only make your development easier, they’re also usable by other developers and in production.


So, the steps to remember for changing the database schema is as follows:
    • Change your models in models.py file.
    • Run python manage.py makemigrations to create migrations for the changes made.
    • Run python manage.py migrate to apply those changes to the database.


Comments

Recent Posts

Archive

2019
2018
2017
2016
2015
2014

Tags

Authors

Feeds

RSS / Atom