January 14, 2021
←前回:Day 8 TemplateViewでテンプレートを表示する
#注意書き
この記事は単一の記事ではありません。
日記として書いているため、初見の方にはお役に立てないかと思います。
「Djangoを学びたい」とのことでありましたら[Day 1]Djangoの開発環境から読むことをおすすめします。
#はじめに
今回のテーマは「モデルの作成」です。
ここまで非常に初歩ですが、ViewとTemplateについて見てきました。
残りはModelですね。
Djangoではモデルに様々な情報をもたせることでデータベースとの連携やバリデーション処理をスマートに行える仕組みを持っています。
今回は掲示板ということで簡単なモデルを作って学習することにしましょう。
#threadアプリケーションの追加
まずはthreadアプリケーションを作ります。これは掲示板のスレッドに関することを処理するアプリケーションです。
(venv)$ ./manage.py startapp thread
baseアプリケーションと同様にthread/urls.pyの追加、mysite/settings.pyにアプリケーションの追加、mysite/urls.pyにURLの追加を行います。
この辺りはbaseアプリケーションと同様です。
[Day 4]アプリケーション作成参考までに
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'django.contrib.sitemaps',
'debug_toolbar',
'base',
+ 'thread',
]
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('base.urls')),
+ path('thread/', include('thread.urls')),
]
from django.urls import path
from . import views
app_name = 'thread'
urlpatterns = [
]
これでアプリケーションの追加処理はOKです。
#モデル追加
threadアプリケーションのモデルは以下の様なものを想定します。
まずは掲示板の最低限の機能を有するように以下のようなモデルを考えます。
from django.db import models
class TopicManager(models.Manager):
# Topic操作に関する処理を追加
pass
class CommentManager(models.Manager):
# Comment操作に関する処理を追加
pass
class CategoryManager(models.Manager):
# Category操作に関する処理を追加
pass
class Category(models.Model):
name = models.CharField(
'カテゴリー名',
max_length=50,
)
url_code = models.CharField(
'URLコード',
max_length=50,
null=True,
blank=False,
unique=True,
)
sort=models.IntegerField(
verbose_name='ソート',
default=0,
)
objects = CategoryManager
def __str__(self):
return self.name
class Topic(models.Model):
user_name = models.CharField(
'お名前',
max_length=30,
null=True,
blank=False,
)
title = models.CharField(
'タイトル',
max_length=255,
null = False,
blank = False,
)
message = models.TextField(
verbose_name='本文',
null=True,
blank=False,
)
category = models.ForeignKey(
Category,
verbose_name='カテゴリー',
on_delete=models.PROTECT,
null=True,
blank=False,
)
created = models.DateTimeField(
auto_now_add=True,
)
modified = models.DateTimeField(
auto_now=True,
)
objects = TopicManager()
def __str__(self):
return self.title
class Comment(models.Model):
id = models.BigAutoField(
primary_key=True,
)
no = models.IntegerField(
default=0,
)
user_name = models.CharField(
'お名前',
max_length=30,
null=True,
blank=False,
)
topic = models.ForeignKey(
Topic,
on_delete=models.PROTECT,
)
message = models.TextField(
verbose_name='投稿内容'
)
pub_flg = models.BooleanField(
default=True,
)
created = models.DateTimeField(
auto_now_add=True,
)
objects = CommentManager()
def __str__(self):
return '{}-{}'.format(self.topic.id, self.no)
#簡単な解説
ここからは上記の(thread/models.py)説明に入ります。
そのため、本家のurlを載せておきます。
本家
以降、リンクに飛ばなくてもいいように説明書きを下に載せておきますが、本家と全く同じなので本家に飛んで参照することをおすすめします。
モデルフィールド
モデルの各クラスのプロパティはモデルフィールドで規定していきます。 公式のモデルフィールドリファレンスにモデルフィールドの種類がまとまっています。Djangoではモデルが持つ関連情報はできるだけ一箇所にまとめることを理想としていて、データベース格納時のデータ型、リレーションに関する情報、デフォルト値、nullの許容等の情報を付与していきます。多くのWeb開発ではAPIの設計、データベース設計を終えた後に実装に入ると思いますので、設計を素直にモデルに書き起こしていく作業となります。nullとblank
nullとblankが出てきました。nullはデータベース上でNULLを許容するかどうか?であり、blankはユーザーが入力項目として必須項目にするかどうかということです。具体的にはblankにFalseを当てるとフォームでインプットタグにrequiredが付きます。IDの自動生成
さて、IDに関する記述がないのに気づきましたか?IDに関しては明記しない場合はDjangoによって自動生成されます。その場合はデータ型はintとなりPrimary Keyが設定されます。外部キー
今回、1対多の関係を構築するためにトピックはカテゴリーのidをコメントはトピックのidを保有しています。このような場合DjangoではForeignKeyを用います。その場合、外部キーとして保有してるモデルが削除された場合の削除方法をon_deleteで指定します。種類としては以下のようなものがあります。models.CASCADE : 外部キーのモデルと一緒に参照しているモデルも削除される
models.PROTECT : 保護される(参照されている場合には削除できない)
models.SET_NULL : 外部キーのモデルが削除された場合IDはNULLとなる
models.SET_DEFAULT : デフォルトで設定されている値がセットされる。
オススメはPROTECTでしょうか。CASCADEは少々リスクが高いですが、設計次第では問題ないと思います。
マネージャーについて
また、今回はTopicManagerとCommentManager,CategoryManagerを用意し、各モデルのobjectsと紐づけました。今後、各モデルに関する操作に関わる処理はこのマネージャーに追加していき、ビューからはその処理を呼び出し、モデルに作用するようにします。慣れない内はViewで多くの処理をしてしまい肥大化しがちですが、モデルが担うビジネスロジックの処理はモデルで行うべきかと(自戒をこめて)考えています。 と、ここまで丁寧に説明してもらえましたが、私はよくわからなかったです。 しかしながら、Djangoのモデルというものがどういうものかは理解でしました。 #おわりに 今回はモデルの作成をしました。大学でSQLを触ったことがあるのでモデルの性質は少し理解することができました。それではまたまた
←前回:Day 8 TemplateViewでテンプレートを表示する
→次回:Day 10 データベースのマイグレーション