Djangoとは

Python製のWEBアプリケーションフレームワーク。 WEBアプリケーションフレームワークとは、WEBアプリケーションを効率的に開発するための機能をまとめたもの。

Python系のWEBアプリケーションフレームワークには、他にも FlaskやBottle、Pyramidなど軽量なWEBアプリケーションもある。

Djangoは、機能が多様で、WEBアプリケーション開発に必要な機能が一通り揃っていることが好まれ、Python系のWEBアプリケーションフレームワークの中でも利用者が多い。 Djaongは以下の要素で構成されている。

prj

URLルーティング

DjaognにおいてURLと、そのURLにアクセスした際の対する処理を定義する仕組み。

ルーティングは、下記の例にあるように、urls.pyで定義する。 path関数は、第一引数に指定したURLのパスに対応する処理を、第二引数に指定する。

下記の例では、“http://example.com/admin"にアクセスした際に、admin.site.urlsを呼び出すようになっている。 また、“http://example.com/app_ur/admin"にアクセスした際に、アプリケーションの urls.py を呼び出すようになる。 ※ includeメソッドを使用すると、アプリケーションのurls.pyを呼び出すことができる。

  • プロジェクト/urls.py
from django.contrib import admin
from django.urls import path, include
from .views import hello_fuction_view
from .views import HelloClassView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app_url/', include('application_name.urls')),
]
  • アプリケーション/urls.py
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

ビュー

DjangoにおいてWEBサイトの見た目を定義する要素。

ルーティングから受けっとたリクエスト情報を元に、レスポンスを返す。 ビューによりリクエストの内容に応じた、WEBページが表示できる。

ビューはviews.pyに定義する。

ビューには関数ベースビューと、クラスベースビューがある。。

関数ベースビュー

HTTPリクエストを引数に、それに対するレスポンスを返す関数

以下は、リクエストを受けた際に、Hello Worldをレスポンスとして返すビューの例。

from django.http import HttpResponse

def hello_fuction_view(request):
    return HttpResponse("<h1>Hello World!</h1>")

クラスベースビュー

Djangoにクラスとして予め実装されているビューのこと。 クラスビューにはデフォルトで基本機能が実装されているので、 関数ビューよりも、簡潔に記述できる。

以下は、リクエストを受けた際に、hello_templateをレスポンスとして返すビューの例。

from django.views.generic import TemplateView

class HelloClassView(TemplateView):
    template_name = "hello_template.html"

urls.pyからビューを呼び出す

urls.py、URLに応じて呼び出すビューを指定する。

from django.contrib import admin
from django.urls import path, include

# ビューをインポート
from .views import hello_fuction_view
from .views import HelloClassView

urlpatterns = [
    # 関数ビューを呼び出す
    path('function_view/', hello_fuction_view),
    # クラスビューを呼び出す
    path('class_view/', HelloClassView.as_view()),
]

フォーム

Djangoにおいてフォーム項目の書式(幅、プレースホルダ)や、フォーム項目に入力された値のチェック(バリデーション)などのフォーム項目に持たせる機能を定義する要素。

forms.pyに定義する。

from django import forms

class SupportForm(forms.Form):

    name = forms.CharField(label='名前', max_length=30)
    email = forms.EmailField(label='メールアドレス')
    title = forms.CharField(label='タイトル', max_length=30)
    message = forms.CharField(label='メッセージ', widget=forms.Textarea)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['name'].widget.attrs['class'] = 'form-control col-9'
        self.fields['name'].widget.attrs['placeholder'] = '田中太郎'

        self.fields['email'].widget.attrs['class'] = 'form-control col-11'
        self.fields['email'].widget.attrs['placeholder'] = 'taro@sample.com'

        self.fields['title'].widget.attrs['class'] = 'form-control col-11'
        self.fields['title'].widget.attrs['placeholder'] = 'タイトル'

        self.fields['message'].widget.attrs['class'] = 'form-control col-12'
        self.fields['message'].widget.attrs['placeholder'] = 'メッセージ'


モデル

DjangoにおいてDBに登録するデータの定義や、DBへの操作する要素。 ビューから受け取ったDBへの操作要求をDBに実行し、実行結果をビューに返す。

models.pyに定義する。


from django.db import models

class SupportModel(models.Model):
    name = models.CharField(max_length=30)
    email = models.CharField(max_length=30)
    title = models.CharField(max_length=30)
    message = models.CharField(max_length=30)
    support_date = models.DateField()

    def __str__(self):
        return self.title

データベースマイグレーション

Djangoにおいてmodels.pyに定義した内容をデータベースに反映させる機能。 マイグレーションは下記の流れで行われる。

  • model.pyからマイグレーションファイルという中間ファイルを生成
  • マイグレーションファイルを読み取り、SQLに変換しデータベースに適用する

model.pyの内容を変更する度にマイグレーションが必要となる。


テンプレート

雛形となるHTMLファイル。 Djangoテンプレート言語という記法に基づいた特殊文字列を記載することが可能。

Djangoテンプレート言語を使用することで、置換文字列や、制御文、繰り返し分をHTMLファイル中に埋め込むことができ、WEBページの内容を動的に変更することが可能。

{% extends "base_generic.html" %}

{% block title %}{{ section.title }}{% endblock %}

{% block content %}
<h1>{{ section.title }}</h1>

{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

https://docs.djangoproject.com/ja/3.0/topics/templates/

変数

変数はDjangoのソースコード中に定義した変数の値を置換したものを表示する。 {{ 変数名 }}のような形式で指定する。

フィルタ

変数の表示内容をカスタマイズする機能。 {{ 変数名|フィルタ }}のような形式で指定する。

下記は日付の表示形式をカスタマイズするフィルタの例。

{{ my_date|date:"Y-m-d" }}

タグ

テンプレートファイルの機能を便利にするもの。 Djangoには様々な組み込みタグがあり、 一般的なプログラミング言語にあるような、制御文や繰り返し文を使用したテンプレートの制御も可能。 タグは {% タグ名 %} のように記載する。

if-elseタグ
{% if user.is_authenticated %}
    Authenticated OK.
{% else %}
    Authenticated NG.
{% endif %}
forタグ
<ul>
{% for item in object_list %}
    <li>{{ item.name }}</li>
{% endfor %}
</ul>
block-extendsタグ

他のテンプレートファイルの内容を継承する際に利用する。

extendsタグに他のテンプレートファイル名を指定すると、そのテンプレートファイルの内容を継承することができる。

自身のテンプレートファイルのblockタグで記載した内容を、 ベースとなるテンプレートファイルにblockタグで定義した箇所に置換できる。

  • base.html
<head>
    <title>{% block title %}{% endblock %}</title>
  {% block head %}{% endblock %}
</head>
  • index.html
{% extends 'base.html' %}

{% block title %}
ページタイトル
{% endblock %}

{% block header%}
<h2>ヘッダメッセージ</h2>
コンテンツの内容を記載      
{% endblock %}

Djangoの設定

settings.pyでDjango全体の設定をすることができる。

設定項目には以下のようなものがある。

  • BASE_DIR

    ベースディレクトリ(Djangoのプロジェクトディレクトリ) のファイルパスの設定

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  • SECRET_KEY

    Djangoの秘密鍵の設定

SECRET_KEY = '+@gc2_!a39wo30b1ayc&$*d6m0s131_db5*qgmltm)@j!(f-iy'
  • DEBUG

    デバッグモードの設定 (エラーが出た際になどにWEBサイトに詳細なメッセージが表示される)

DEBUG = True
  • ALLOWED_HOSTS
    アクセス許可をするホストの設定 (※ 通常は公開するWEBサーバのドメイン名を指定する)
# 全てのホストからのアドレスを許可する場合
ALLOWED_HOSTS = ['*']

# WEBサーバのドメインと、localhostからのアクセスを許可場合
ALLOWED_HOSTS = ['exsample.com', 'localhost']  
  • INSTALLED_APPS

    利用するDjangoの機能の設定するための項目。

# django.contrib.admin(管理サイト用WEBアプリケーション)を利用する場合
INSTALLED_APPS = [
  'django.contrib.admin'
]
  • MIDDLEWARE

    ミドルウェアの設定(セッションの維持などの設定)を行う項目

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
]
  • ROOT_URLCONF

    WEBサイトのルートとなるURLの設定を行う項目

ROOT_URLCONF = 'sample_project.urls'
  • TEMPLATES

    テンプレートファイルの設定(ディレクトリのファイルパスの設定など)を行う項目

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
  • WSGI_APPLICATION

    PythonとDJANGOとなるWSGIファイルのファイルパスを設定を行う項目

WSGI_APPLICATION = 'sample_project.wsgi.application'
  • DATABASES

    Djangoが使用するDBの設定 (DBエンジン、ファイルパスなど)を行う項目

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'django_db',
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': '',
        'PORT': '',
    }
}
  • AUTH_PASSWORD_VALIDATORS

    パスワードチェックの規則の設定を行う項目

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]
  • LANGUAGE_CODE

    使用する言語の設定を行う項目

LANGUAGE_CODE = 'ja'
  • STATIC_URL

    WEBサーバがCSS、JavaScriptなどの静的ファイルを読み取るために、静的ファイルが保存されているURLのパスを指定する項目

STATIC_URL = '/static/'
  • STATIC_ROOT

    静的ファイルを一箇所にまとめるコマンドmanage.py collectstaticを実行したときに静的ファイルがまとめられるディレクトリのパスを指定する項目。

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
  • STATICFILES_DIRS

    Djangoが静的ファイルを読み取るために、静的ファイルが保存されているのディレクトリのパスを指定する項目。

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

Django関連の開発環境

Nginx

WEBサーバの機能を提供するOSS。 大量のリクエストアクセスをさばくことに長けている。


Gunicorn(Green Unicorn)

PythonのWGSGIのひとつ。 WSGI(Web Server Gateway Interface)とは、WEBサーバとWEBアプリケーションを接続させるためのインターフェースの仕様である。

https://wsgi.readthedocs.io/en/latest/


Bootstrap

BootstrapはTwitter社が開発したCSSの「フレームワーク」。 WEBページでよく使われるフォーム・ボタン・メニューなどの部品がテンプレートとして用意されている。

https://getbootstrap.com


Djangoの環境の構築

環境構成

以下の環境でDjango環境を作成する。

  • OS : CentOS 7.6
  • DB : PostgreSQL
  • WEBサーバ : Nginx

パッケージのインストール

$ yum install -y python3-pip python3-dev
$ yum install -y libpq-dev postgresql postgresql-contrib
$ yum install -y nginx

DBの設定

Django用に使用するDB(django_db)とユーザ(django_user)を作成する。

$ sudo -u postgres psql

> CREATE DATABASE django_db;
> CREATE USER django_user WITH PASSWORD 'password';
> ALTER ROLE django_user SET client_encoding TO 'utf8';
> ALTER ROLE django_user SET default_transaction_isolation TO 'read committed';
> ALTER ROLE django_user SET timezone TO 'UTC';
> GRANT ALL PRIVILEGES ON DATABASE django_db TO django_user;

# DBが作成されていることを確認
> \l

# ユーザが作成されていることを確認
> SELECT * FROM pg_shadow;
> \q

pythonの仮想環境の構築

$ /usr/local/bin/pip3 install virtualenv
$ mkdir -p /opt/virtualenv
$ cd /opt/virtualenv
$ virtualenv django_env

Djangoのインストール

$ source /opt/virtualenv/django_env/bin/activate
$ pip install django gunicorn psycopg2-binary

Djangoプロジェクトの作成

$ mkdir -p /opt/django
$ cd /opt/django/
$ django-admin startproject sample_project

ディレクトリの作成

静的ファイルと、テンプレートファイルを保存するディレクトリを作成する。

$ mkdir -p /opt/django/sample_project/static
$ mkdir -p /opt/django/sample_project/templates

Djangoの設定変更

settings.pyに対して、デフォルトで作成されたものから、以下の点を変更する。

  • アクセスする許可するホストを変更
ALLOWED_HOSTS = ['example.com', 'localhost']
  • テンプレートのディレクトリを変更。

TEMPLELATEのDIRSを以下のように変更する。 これにより、プロジェクトディレクトリ直下のtemplatesというディレクトリがテンプレートに指定される。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
  • DATABASEをPostgreSQLに設定

デフォルトだとSQLiteが設定されているので、postgresqlに変更する。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'django_db',
        'USER': 'django_user',
        'PASSWORD': 'password',
        'HOST': '',
        'PORT': '',
    }
}
  • 言語とタイムゾーンを日本環境に設定する

日本語環境に設定するため、以下のように設定を行う。

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
  • 静的ファイルのパスを設定

静的ファイルを配置するパスをプロジェクト直下のstaticディレクトリに設定する。

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

Djangoアプリケーションの作成

以下のコマンドを実行するとプロジェクトのディレクトリ直下にアプリケーション用のディレクトリが作成される。

$ cd /opt/django/sample_project
$ python manage.py startapp sample_application

データベースマイグレーション

$ python manage.py makemigrations
$ python manage.py migrate

Djangoの管理者ユーザを作成

管理画面にログインする際の管理者ユーザー (スーパーユーザー)を設定する。

$ python manage.py createsuperuser
# 以下のように入力する
> ユーザー名 (leave blank to use 'root'): admin
> メールアドレス: admin@test.com
> Password: admin_1234
> Password (again): admin_1234
> Superuser created successfully.

静的ファイルを作成

/opt/django/sample_project/staticにcssなどの静的ファイルを移動させる。

$ python manage.py collectstatic

ファイアウォール設定の解除

ポート8080を開放する。

$ firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" port protocol="tcp" port="8080" accept"

gunicornをsystemdに登録

下記の2ファイルを作成。

  • /etc/systemd/system/gunicorn.socket

Nginxからアクセスを受けるソケットの設定。

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

User=www-data

[Install]
WantedBy=sockets.target
  • /etc/systemd/system/gunicorn.service

socketからアクセスを受けた時にgunicornを起動させる設定を行う。

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=root
Group=root
WorkingDirectory=/opt/web/request_generator
ExecStart=/opt/web/request_generator/request_generator_venv/bin/gunicorn \
    --access-logfile - \
    --workers 3 \
    --bind unix:/run/gunicorn.sock \
    request_generator.wsgi:application

[Install]
WantedBy=multi-user.target

gunicornをsystemdに登録して、起動させる。

$ systemctl enable gunicorn.socket
$ systemctl start gunicorn.socket

https://docs.gunicorn.org/en/stable/deploy.html


Nginxの設定

以下のファイルを作成する。

  • /etc/nginx/conf.d/gunicorn.conf

ポート8080でNginxにリクエストした際に、Gunicornのソケットファイル(gunicorn.sock)にリクエストをプロキシする設定を実施。

server {
    listen 8080;
    server_name example.com # WEBサーバのドメイン名
    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /opt/django/sample_project; # djangoのプロジェクトディレクトリ
    }
    location / {
        proxy_pass http://unix:/run/gunicorn.sock;
        #proxy_pass http://127.0.0.1:8000;
    }
}

設定を反映させるため、Nginxを再起動する。

$ systemctl enable nginx.service
$ systemctl restart nginx.service

WEBサーバを経由してWEBサイトを表示

WEBブラウザで下記のアドレスにアクセスすると、DJANGOのサンプルページにアクセスできる。

http://exsample.com:8080