Python Django お問い合わせ管理サイトを作る その2(モデルの作成)

Django

今回は、お問い合わせ内容を管理するためのモデルを作成していきます。
データを管理するためにデータベースを利用しますが、Djangoでは、これを簡単に行うことが
できるように仕組みが用意されています。
通常、データベースにテーブルを作成して、データを操作するためのSQLを書いて といった
作業が発生しますが、このあたりをDjangoがうまくやってくれます。
データベースの知識がなくても作れちゃいます。

前回までの内容

前回までに作成したサイトは、以下のようなものでした。(見ていない方はこちらへ)

プロジェクト名DjangoProject
アプリ名DjangoApp
フロントエンドフレームワークBootstrap4
サイトで使用するWebフォントGoogle Kosugi
フォルダ構成
.
├── DjangoApp
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── admin.cpython-36.pyc
│   │   ├── models.cpython-36.pyc
│   │   ├── urls.cpython-36.pyc
│   │   └── views.cpython-36.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-36.pyc
│   ├── models.py
│   ├── static
│   │   └── DjangoApp
│   │       ├── css
│   │       │   └── style.css
│   │       ├── img
│   │       │   └── logo.png
│   │       └── js
│   ├── templates
│   │   └── DjangoApp
│   │       ├── base.html
│   │       ├── dashboard.html
│   │       ├── footer.html
│   │       ├── head.html
│   │       ├── header.html
│   │       ├── inquiry_menu.html
│   │       └── javascripts.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── DjangoProject
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── settings.cpython-36.pyc
│   │   ├── urls.cpython-36.pyc
│   │   └── wsgi.cpython-36.pyc
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── db.sqlite3
└── manage.py
外観

管理するデータを定義する

お問い合わせ内容を管理するためのデータとして以下を定義します。

お問い合わせ内容を定義するモデル
  • 顧客名
  • 受付日時
  • カテゴリー
  • 受付内容
  • 申し送り事項
  • 緊急度
  • ステータス
  • 入力日時
  • 入力者名
  • 更新日時
  • 更新者名

カテゴリーは、別のモデルで定義した値から選ぶようにします。

カテゴリーモデル
  • カテゴリ名

モデルを作成する

上で考えたモデルを作成していきます。
モデルを定義するには、DjangoApp/models.pyファイルにモデルクラスを作成してあげます。

models.py
from django.db import models

# Create your models here.
class Customer(models.Model):
    customer = models.CharField(
        verbose_name='お客様名', max_length=100, unique=True)

    def __str__(self):
        return self.customer


class Category(models.Model):
    category = models.CharField(
        verbose_name='顧客名',
        max_length=100,
        unique=True, 
    )

    def __str__(self):
        return self.category


class Inquiry(models.Model):

    EMERGENCY = (
        (0, '通常'),
        (1, '緊急'), 
    )
    
    STATUS = (
        (0, '受付'),
        (1, '対応中'),
        (2, '対応済み'), 
    )

    subject = models.CharField(
        verbose_name='件名',
        max_length = 200, 
    )
    customer = models.CharField(
        verbose_name='顧客名',
        max_length=100, 
    )
    reception_datetime = models.DateTimeField(
        verbose_name='受付日時'
    )
    category = models.ForeignKey(
        Category,
        on_delete=models.SET_NULL,
        null=True, 
        verbose_name='カテゴリー')
    content = models.TextField(
        verbose_name='受付内容',
    )
    request = models.TextField(
        verbose_name='申し送り事項', 
    )
    emergency = models.IntegerField(
        verbose_name='緊急度',
        choices=EMERGENCY,
        default=0, 
    )
    status = models.IntegerField(
        verbose_name='ステータス',
        choices=STATUS,
        default=0, 
    )
    user_posted = models.CharField(
        verbose_name='入力者名',
        max_length=10,  
    )
    date_posted = models.DateTimeField(
        verbose_name='入力日時',
        auto_now_add=True, 
    )
    user_updated = models.CharField(
        verbose_name='更新者名',
        max_length=10, 
    )
    date_updated = models.DateTimeField(
        verbose_name='更新日時',
        auto_now=True, 
    )

    def __str__(self):
        return self.subject

各モデルは、models.Modelクラスを継承して定義します。
このクラスのプロパティとして、必要なフィールドを定義していきます。

用意されているフィールドの型は、こちらでご確認ください。

各フィールドの引数に定義されているverbose_nameは、フィールドの論理名に相当します。
これを定義しておくと、このモデルのデータを作成するフォームを作るときに入力者がわかりやすい名前で表示することが可能になります。(htmlにごりごり論理名を直接書くこともできますが)

一つ、他のフィールド定義と異なるのが、ForeignKeyを指定しているcategoryフィールドです。
これは、別に定義されているCategoryモデルと外部キー制約の関係で結ばれていることを表しています。この場合、Categoryモデルに定義されていない値をInquiryモデルに登録することはできません。
あと、ForeignKeyフィールドの場合、on_deleteの値を必ず指定しなければなりません。
これは、外部キー制約の関係にあるデータを削除するとき(この場合は、Categoryモデルのデータを削除するとき)、紐付いたデータをどのように扱うかを決める値です。

CASCADEレコードごと一緒に削除します
PROTECT削除できないようにします
SET_NULLフィールドにNULLをセットします
SET_DEFAULTフィールドに定義されたデフォルト値に修正します
DO_NOTHING何もしません
on_deleteに指定できる値

モデルをデータベースに反映させる

やることは、2つです。

  • マイグレーション情報の作成
  • マイグレーションの実行

マイグレーションって。。。
マイグレーション(migration)自体は、別の環境やバージョンなどへの移行を意味する単語です。
今回の場合は、特にデータベースマイグレーションと呼ばれるケースに当たり、
モデルで定義した情報をデータベースへ反映させるための作業を自動的に作成、管理してくれる機能になります。
したがって、SQLの書き方がわからなくてもこの機能が変わりにやってくれちゃいます。

マイグレーション情報の作成は、以下のコマンドを実行します。

python manage.py makemigrations

実行してみると、コンソールに以下のように出力されます。

Migrations for 'DjangoApp':
  DjangoApp/migrations/0001_initial.py
    - Create model Category
    - Create model Customer
    - Create model Inquiry

0001_initial.pyファイルが実際に出力された場所にできていることがわかります。
この情報をもとに、次のマイグレーションの実行が行われます。
ファイルを開いてみてみるとわかりますが、この段階では、SQLが生成されているわけではありません。SQLを生成するための中間ファイルが作成されているのです。

ファイルを見てもう一つ気づくのが、定義していないidフィールドが勝手に追加されていることです。これは、djangoがレコードを一意に特定するために自動的に作成するプライマリーキーフィールドになります。
プライマリーキーフィールドは、自分で作成したフィールドに明示的に指示することもできます。

実際のSQLの生成・実行(マイグレーションの実行)は、以下のコマンドを実行することで行われます。

python manage.py migrate

コンソール上に以下のように表示されます。

Operations to perform:
  Apply all migrations: DjangoApp, admin, auth, contenttypes, sessions
Running migrations:
  Applying DjangoApp.0001_initial... OK
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... 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 auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

すべて、OKと表示されていれば成功です。
2つのテーブルを用意するのにずいぶんいろいろと表示されています。
これは、初回実行時には、Djangoがサイトを管理するのに必要なテーブルを合わせて一緒に作っているためです。ユーザーを管理するためのテーブル等が自動的に用意されます。

今回は、ここまでにします。
次回、このモデルを利用してデータを入力・表示するための画面作成に入っていきます。

コメント

タイトルとURLをコピーしました