[PYTHON] A series of amateur infrastructure engineers touching Django with Docker (2): Creating a model

TL;DR Continuation of Amateur infrastructure engineer touches Django with Docker (1): Make Django with Docker. I will create a model in django that I made last time. There is a site called Django Girls that has a tutorial on django, so this time I will sample the blog according to the chapters after "Django model" of it. Play with django while creating it. (This site is very easy to understand, and honestly it may be better than looking at this post, but by disclosing the learning process and research when an amateur touched it, people of the same level I am writing with the aim of promoting understanding.)

Django design policy

Model - Template - View Django seems to be designed with the idea of MTV (model template view). I've heard of MVC (Model View Controller) (only the name). .. Check one by one.

Model The model interacts with the database. In the DjangoGirls blog example, after mentioning object orientation, the following is listed as necessary data for the blog.

Post
--------
title
text
author
created_date
published_date

Such a data format that will be needed is defined as a model, and when a request comes, the required data is fetched from the DB and returned. This seems to be about the same as Model's role in MVC. (Perhaps)

Template Templates in Django refer to the good looking part. That is html and CSS and javascript to complement it. In MVC, the role of View. It's complicated. .. In MVC, the Controller bridges the Model and View, and the Template in MTV does not get data directly from the Model. Be sure to handle data through View.

View As I mentioned a little in Template, View describes how to show the information acquired by using Model. After that, it is made into a function and linked with Template. In other words, as a role, ① Issue a data acquisition command to Model ② Determine the Template to be returned to the user's request ③ Pass the data obtained from Model to Template as a function There are three. (I'm not very confident, but if I make a mistake, I'll fix it, so please point it out.) When a user visits a website made with django, first decide which View function to process according to the description in urls.py, and the selected View function uses Model to get the data and use it as the selected template. Display the web page after passing the data.

Is the image somehow like the following?  U  ⇒ urls.py ⇒ view.py ⇔ Model ⇔ DB  S        ⇓  E        ⇓  R  ⇐    Templates

With a soft awareness of these three roles, proceed to construction.

Build

① Create application template

manage.py startapp

docker-compose run web python manage.py startapp blog

Create an application template in the local environment using docker-compose.yaml created last time. Last time, manage.py was used for runserver to start web server, but startapp will create the files necessary to create a model. The directory structure after executing this command, including the previous execution, should be as follows.

.
∟ blog
  ∟ admin.py
  ∟ apps.py
  ∟ __init__.py
  ∟ migrations
  ∟ models.py
  ∟ tests.py
  ∟ views.py
∟ composeexample
  ∟ __init__.py
  ∟ __pycache__
  ∟ settings.py
  ∟ urls.py
  ∟ wsgi.py
∟ docker-compose.yaml
∟ Dockerfile
∟ manage.py
∟ migrations
∟ requirements.txt

As before, if you run it on a linux machine, the folder permissions will be root, so do the following:

sudo chown -R $USER:$USER .

② Linking with settings.py

settings.py

settings.py


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

Add the application created this time to INSTALLED_APPS.

③ Model creation

models.py

blog/models.py


from django.conf import settings
from django.db import models
from django.utils import timezone


class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

Create a model definition. There is models.py in the blog folder created by startapp, so edit it. From the beginning, only the second line, from django.db import models, is borrowed, and the Django Girls sample is borrowed.

Well-understood commentary

from django.conf import settings

Module used when referencing variables in project / settings.py.

from django.db import models

A module that provides various methods for model. Foreign keys, data types, etc.

from django.utils import timezone

Module about time zone. It's almost the same as the utility provided in various languages. This time I'm using it to get the time at the time of posting. Since the timezone is set in settings.py, it should be UTC in the current situation where nothing is done.

class Post(models.Model):

The part that defines the model called Post. The model to be defined is created by inheriting django.db.models.Model. It is also possible to create child classes. For example, create_date may be used in other models for general purposes, so create a Timestamp class that defines create_date data and inherit it in the form of Post (Timestamp).

    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

ForeignKey () defines a model that is a foreign key. This time, in order to specify the User model that django has by default as a foreign key, the MODEL definition is acquired using the settings module, but if you normally use the model you created as a foreign key, the model Specify the name. The on_delete option is required in django 2.0 or later, and specifies the behavior when a foreign key object is deleted. CASCADE deletes all associated objects when it deletes a foreign key object.

    title = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

Specify the data types and constraints that make up the blog. For created_date, the time when the object was created is entered. That is, the time when the article was written. On the other hand, published_date is blank at the moment, and the value is entered in the publish method described later.

    def publish(self):
        self.published_date = timezone.now()
        self.save()

A method for publishing blog articles. The current time is assigned to published_date, which is the published time, and the save () method is called. I don't remember writing the save () method, so of course, in the method in the inheritance source models.Model, if the primary key exists in the table, UPDATE and if it does not exist, CREATE it.

    def __str__(self):
        return self.title

magic method. (Because it is not the main point about the magic method, please check it yourself.) The title of the blog article is returned when it is instantiated.

④ Database migration

In django, creating a table in the database connected with the contents of models.py seems to be called migration. When you execute the command manage.py makemigrations, a file for migration is created, and the command manage.py migrate actually creates a table on the database. Immediately enter the web server with docker-compose exec, execute the command, enter the db server and check if the table is created. (These operations will be added to the command in docker-compose later so that migration will be performed with docker-compose up, but now I am entering the container and executing the command for confirmation)

docker-compose exec web bash

(Hereafter in the web container)

manage.py makemigrations blog

The following output is output. blog/migrations/0001_initial.py

manaeg.py migrate blog

Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying blog.0001_initial... OK If the output is as above, the migration is complete. Exit the web server with exit and enter the db server to check.

docker-compose exec db bash

(Hereafter in the db container)

psql -U postgres
\d

\d Execution result


                        List of relations
 Schema |               Name                |   Type   |  Owner
--------+-----------------------------------+----------+----------
 public | auth_group                        | table    | postgres
 public | auth_group_id_seq                 | sequence | postgres
 public | auth_group_permissions            | table    | postgres
 public | auth_group_permissions_id_seq     | sequence | postgres
 public | auth_permission                   | table    | postgres
 public | auth_permission_id_seq            | sequence | postgres
 public | auth_user                         | table    | postgres
 public | auth_user_groups                  | table    | postgres
 public | auth_user_groups_id_seq           | sequence | postgres
 public | auth_user_id_seq                  | sequence | postgres
 public | auth_user_user_permissions        | table    | postgres
 public | auth_user_user_permissions_id_seq | sequence | postgres
 public | blog_post                         | table    | postgres
 public | blog_post_id_seq                  | sequence | postgres
 public | django_content_type               | table    | postgres
 public | django_content_type_id_seq        | sequence | postgres
 public | django_migrations                 | table    | postgres
 public | django_migrations_id_seq          | sequence | postgres

There are many tables. auth and django are probably created by default (probably). Since I wrote blog_post in models.py, check the definition of the blog_post table.

\d blog_post

\d Execution result


                                         Table "public.blog_post"
     Column     |           Type           | Collation | Nullable |                Default
----------------+--------------------------+-----------+----------+---------------------------------------
 id             | integer                  |           | not null | nextval('blog_post_id_seq'::regclass)
 title          | character varying(200)   |           | not null |
 text           | text                     |           | not null |
 created_date   | timestamp with time zone |           | not null |
 published_date | timestamp with time zone |           |          |
 author_id      | integer                  |           | not null |
Indexes:
    "blog_post_pkey" PRIMARY KEY, btree (id)
    "blog_post_author_id_dd7a8485" btree (author_id)
Foreign-key constraints:
    "blog_post_author_id_dd7a8485_fk_auth_user_id" FOREIGN KEY (author_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED

id is a serial number given by default when django defines a model, and is the primary key. Others are as defined in models.py. The model is now ready.

It feels like the second step at last, but let's do it without fail. ..

Continued

Recommended Posts

A series of amateur infrastructure engineers touching Django with Docker (2): Creating a model
A series of amateur infrastructure engineers touching Django with Docker ③: Django admin
Creating a Flask server with Docker
Deploy a Django application with Docker
Creating a login screen with Django allauth
[Python] Build a Django development environment with Docker
Flow of creating a virtual environment with Anaconda
Looking back on creating a web service with Django 1
Looking back on creating a web service with Django 2
A memo about building a Django (Python) application with Docker
Launch Django on a Docker container with docker-compose up
Build a development environment with Poetry Django Docker Pycharm
Impressions of touching Django
Web App Development Practice: Create a Shift Creation Page with Django! (Design of database model)
Build a Django development environment with Docker! (Docker-compose / Django / postgreSQL / nginx)
[Memo] Build a development environment for Django + Nuxt.js with Docker
The story of a Django model field disappearing from a class
[Django] Build a Django container (Docker) development environment quickly with PyCharm
Create a Todo app with Django ① Build an environment with Docker
(For beginners) Try creating a simple web API with Django
Analyze the topic model of becoming a novelist with GensimPy3
Create a homepage with django
Creating a Tensorflow Sequential model with original images added to MNIST
Here's a brief summary of how to get started with Django
I made a development environment for Django 3.0 with Docker, Docker-compose, Poetry
[DynamoDB] [Docker] Build a development environment for DynamoDB and Django with docker-compose
Building a distributed environment with the Raspberry PI series (Part 1: Summary of availability of diskless clients by model)