[PYTHON] Learning notes for the migrations feature in the Django framework (1)

Creating web applications using the Django framework is very convenient. If you compare the MVC model, it implements complicated details in the Model and View parts, helping the programmer to focus on what he wants to do (Control). This time, I would like to describe migrations related to the Model part. Refer to Django Official Tutorial for Django's Project creation settings, and [here](https://docs. djangoproject.com/en/1.11/topics/migrations/#historical-models) is referenced.

What are migrations?

Translated into Japanese, migrations means "migration." In Django, it's primarily about the ability to automatically change user-designed data structures into a database schema (you can write a migrations file manually, but I'll show you more if I get the chance).

Let's use it first

Let's create an app by referring to Tutorial (however, only the data model part).

Development environment
Mac OS:Sierra
python2.7.10
django1.11.2
mysql5.7.18

Enter the working directory and enter the following command in the terminal:

django-admin startproject m_Migration
python manage.py startapp polls

You have now created a polls app in the project m_Migration and inside. Next, set up the database. It uses mysql instead of the default sqlite, so You need to modify the project settings file.

Django database settings

  1. Launch mysql and create the user and user password and the database to be used this time.
  2. Modify settings.py in the project package according to the attributes created in 1 (see [here](https://docs.djangoproject.com/en/1.11/ref/settings/#core- for details) See settings).
python:settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'blog',
        'USER':'user',
        'PASSWORD':'',
        'HOST':'',
        'PORT':'3306',
    }
}

After that, reflect the initial settings in the terminal.

python manage.py migrate

log:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying sessions.0001_initial... OK

If you go into the mysql client and look at the tables you currently have in the database blog:

+----------------------------+
| Tables_in_blog             |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+

A framework-related database has been created. Currently only polls apps have a model.py module, so the polls package created a migrations folder.

Let's create a model

Create a data model Category and Article for use in the polls app.

models.py



# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.
class Category(models.Model):
    name = models.CharField(max_length=100)


class Article(models.Model):
    title = models.CharField(max_length=100)
    text = models.CharField(max_length=1000)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

The function of the polls app is to display saved blog posts. Therefore, we created an article model Article and a Category model that shows the genre of the article. In order to reflect the created model, first create a migrations file that describes the operation.

python manage.py makemigrations polls

log:

Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Article
    - Create model Category
    - Add field category to article

Here, in the migrations / folder, I created a migrations file 0001_initial.py that records the changes to model.py this time. Next, reflect the created migrations file

python manage.py migrate

log:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

Now in the database

+----------------------------+
| Tables_in_blog             |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| polls_article              |
| polls_category             |
+----------------------------+

Looking at the table schema:

mysql>DESC polls_article;
+-------------+---------------+------+-----+---------+----------------+
| Field       | Type          | Null | Key | Default | Extra          |
+-------------+---------------+------+-----+---------+----------------+
| id          | int(11)       | NO   | PRI | NULL    | auto_increment |
| title       | varchar(100)  | NO   |     | NULL    |                |
| text        | varchar(1000) | NO   |     | NULL    |                |
| category_id | int(11)       | NO   | MUL | NULL    |                |
+-------------+---------------+------+-----+---------+----------------+
mysql>DESC polls_category;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(100) | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+

A new polls app table (polls_article, polls_category) has been created according to the model (id field is automatically created by default). So far, the flow of designing a model with an app and creating a database using django's migrations function.

Common use cases

We may create it once and then modify the data model, such as adding new features.

Data model update

Take the polls app as an example. For example, the original blog service provided articles with only text, but since I bought a good digital camera, the up owner wants to add a photo to the article. Now let's add a field image_url to the Article model to store the photo url (also set the default value for existing records).

models.py


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.
class Category(models.Model):
    name = models.CharField(max_length=100)


class Article(models.Model):
    title = models.CharField(max_length=100)
    text = models.CharField(max_length=1000)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    image_url = models.URLField(max_length=200, default='toBeImplement')

Record your changes

python manage.py makemigrations polls

log:

Migrations for 'polls':
  polls/migrations/0002_article_image_url.py
    - Add field image_url to article

A new migrations file 0002_article_image_url.py has been created.

Reflect the changes.

 python manage.py migrate

Database Let's take a look at the current schema:

DESC polls_article;
+-------------+---------------+------+-----+---------+----------------+
| Field       | Type          | Null | Key | Default | Extra          |
+-------------+---------------+------+-----+---------+----------------+
| id          | int(11)       | NO   | PRI | NULL    | auto_increment |
| title       | varchar(100)  | NO   |     | NULL    |                |
| text        | varchar(1000) | NO   |     | NULL    |                |
| category_id | int(11)       | NO   | MUL | NULL    |                |
| image_url   | varchar(200)  | NO   |     | NULL    |                |
+-------------+---------------+------+-----+---------+----------------+

I was able to update the database as planned.

Data model recovery

You can also control the version of the data model, like VCS such as git. One of the highlights of this feature is the recovery of data models in emergencies. Assuming that I made the changes related to the photo url in the above example, I ran the migrate command with the migrations file 0002_article_image_url.py created.

 python manage.py migrate

Here migrate failed. The latest migrations state is 0002_article_image_url.py, but the actual database schema corresponds to 0001_initial.py. In this state, there is no column corresponding to the photo url in the table. I get an error when I try to access the photo url data from the polls app. One workaround for this issue is to restore the state of migrations to 0001_initial.py (and then look for the bag).

To recover, also use the migrate command to recover to the state recorded in the migrations file 0001_initial.py.

python manage.py migrate polls 0001_initial

log:

Operations to perform:
  Target specific migration: 0001_initial, from polls
Running migrations:
  Rendering model states... DONE
  Unapplying polls.0002_article_image_url... OK

As the log shows, the changes in 0002_article_image_url.py have been unapplyed. Let's take a look at the current Article table schema:

DESC polls_article;
+-------------+---------------+------+-----+---------+----------------+
| Field       | Type          | Null | Key | Default | Extra          |
+-------------+---------------+------+-----+---------+----------------+
| id          | int(11)       | NO   | PRI | NULL    | auto_increment |
| title       | varchar(100)  | NO   |     | NULL    |                |
| text        | varchar(1000) | NO   |     | NULL    |                |
| category_id | int(11)       | NO   | MUL | NULL    |                |
+-------------+---------------+------+-----+---------+----------------+

The table has returned to its original state.

Recommended Posts

Learning notes for the migrations feature in the Django framework (2)
Learning notes for the migrations feature in the Django framework (3)
Learning notes for the migrations feature in the Django framework (1)
Miscellaneous notes about the Django REST framework
List method for nested resources in Django REST framework
How to write custom validations in the Django REST Framework
Summary of stumbling blocks in Django for the first time
Launch notes for existing Django applications
Learning history for participating in team app development in Python ~ Django Tutorial 5 ~
Learning history for participating in team app development in Python ~ Django Tutorial 4 ~
Learning history for participating in team app development in Python ~ Django Tutorial 1, 2, 3 ~
Switch the language displayed in Django 1.9
Learning history for participating in team app development in Python ~ Django Tutorial 6 ~
Learning history for participating in team app development in Python ~ Django Tutorial 7 ~
The meaning of ".object" in Django
Start Django for the first time
Summary of pages useful for studying the deep learning framework Chainer
Get the query string (query string) in Django
Get the client's IP address in Django
Introducing the BOT framework Minette for Python
Logical deletion in Django, DRF (Django REST Framework)
Understand the benefits of the Django Rest Framework
Django ~ Let's display it in the browser ~
Notes on nfc.ContactlessFrontend () for nfcpy in python
Learning notes from the beginning of Python 1
Notes on creating static files in Django
Change the list in a for statement
Same-Site attribute setting for cookies in Django
Get query parameters for GET requests in Django
MongoDB for the first time in Python
Notes for using python (pydev) in eclipse
Learning notes from the beginning of Python 2
Try hitting the Spotify API in Django.
[Reinforcement learning] Search for the best route
Redo everything for the Django login screen
I tried to predict the change in snowfall for 2 years by machine learning
Feature engineering for machine learning starting with the 4th Google Colaboratory --Interaction features
Django notes
How to install the deep learning framework Tensorflow 1.0 in the Anaconda environment of Windows
The _authenticate_with_backend function was obsolete in django auth.autenticate
CERTIFICATE_VERIFY_FAILED in Python 3.6, the official installer for macOS
The story of low learning costs for Python
Upgrade the Azure Machine Learning SDK for Python
Tips for hitting the ATND API in Python
Notes for implementing simple collaborative filtering in Python
Specify the view URL in your Django template
The story of viewing media files in Django
Implement JWT login functionality in Django REST framework
[Implementation for learning] Implement Stratified Sampling in Python (1)
[Django] css in the project cannot be read
Do an ambiguous search for mysql in Django
Knowledge notes needed to understand the Python framework
Implementing authentication in Django REST Framework with djoser
[For beginners] Introduction to vectorization in machine learning
I installed Chainer, a framework for deep learning
Let's reproduce the math teaching tool "Jamaica" ❗️ vol.02 "Notes for creating functions in Python"
Let's reproduce the math teaching tool "Jamaica" ❗️ vol.01 "Notes for displaying images in Python"