Djangoでモデル(データベース)の設定を行うにはmodels.pyに設定を記載します。Djangoにはデータベースを管理する仕組みが搭載されていて多様なDBを扱うことができます。
Djangoのモデルの記述方法を学ぶと、直接SQL文を書かずにDBを扱うことができてとても便利です。
Modelの作成
Personというテーブルを作成するときは以下のように記載します。
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
Class [テーブル名] (models.Model): でテーブル名を指定します。
その下にカラムの設定を行います。Filedに使う設定の一覧です。
Filed一覧
Field | 説明 |
CharField | 文字列 |
TextField | 文字列(長い) |
IntegerField | 整数 |
PositiveIntegerField | 0または正の整数 |
FloatField | 浮動小数点 |
BooleanField | True / False |
JSONField | JSONエンコードされたデータ |
DateTimeField | 日付・時刻 |
DateField | 日付 |
TimeField | 時刻 |
EmailField | メールアドレス(@マークが無いとエラー) |
URLField | URL(http , https , ftp , ftpsが無いとエラー) |
GenericIPAddressField | IP Address |
FileField | ファイル |
ImageField | 画像ファイル |
SlugField | 文字列限定(アルファベット・数字・アンダーバー・ハイフン) |
Django Model名の命名規則
モデル名は基本的に単数形で定義します。Django管理用画面では複数形のsが付いて表示されます。(こちらはDjangoが自動で複数形にしています)
キャメルケース記述で Category、複数の単語をつなげるときは SampleCategoryのようにします。
categoryの複数形はcategoriesですが、DjangoだとCategorysと単純に後ろにsが付いた形になります。これはMetaオプションで修正することができます。
class Meta:
verbose_name_plural = 'Categories'
Django Modelの属性(カラム)命名規則
Django Modelの属性はスネークケースで書きます。category_nameの形式です。
よく使うものは命名の規則を決めておくと可読性が良くなります。
_name , _code , _id , _no , _date , _time , _dt(日時), _num , _type , is_(真偽値) , _file など
Fieldの詳細設定方法
CharField
# 最大文字数を設定(最大255まで)
title = models.CharField(max_length=255)
#TextField
text = models.TextField()
max_lengthは設定しないと「CharFields must define a ‘max_length’ attribute.」エラーが出ます。255文字以上になる場合はCharFieldではなく、TextFieldを使います。
BooleanField
# 初期値(noneにする)
isExist = models.BooleanField()
#初期値(Trueに設定)
isExist = models.BooleanField(default=True)
#初期値(Falseに設定)
isExist = models.BooleanField(default=False)
DateTimeField / DateField / TimeField
日付時間型のオプションは「auto_now_add」と「auto_now=True」になります。
#最初に作成されたときに現在の日時等が保存される
created_at = models.DateTimeField(auto_now_add=True)
#更新されるときに現在の日時等が保存される。
updated_at = models.DateTimeField(auto_now=True)
FileField
ファイルを登録する場合、パスと拡張子を指定するオプションがあります。
file = models.FileField(upload_to='uploads/%Y/%m/', validators=[FileExtensionValidator(['txt'])])
ImageField
画像を登録するときもファイルと同様、パスと拡張子を指定するオプションがあります。
FieldOption
# null
# DBでNullを使えるように・使えないようにする。
hoge = models.BooleanField(null=True)
hoge = models.BooleanField(null=False)
#blank
#カラムへの入力を必須にする(必須にしない)の選択
hoge = models.BooleanField(blank=True)
hoge = models.BooleanField(blank=False)
#choice
#指定したデータから選択できるようにする
class Person(models.Model):
SHIRT_SIZES = [
("S", "Small"),
("M", "Medium"),
("L", "Large"),
]
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
#default
#データを指定しない場合TrueがDBに保存される
hoge = models.BooleanField(default=True)
#primary_key
#idではなくhogeをプライマリーキーに設定する場合
#指定が無いとDjangoがIntegerFieldが自動に生成されてそれが主キーとなる。
hoge = models.CharField(max_length=100, primary_key=True)
#unique
#重複を防止するための設定
hoge = models.PositiveIntegerField(unique=True)
#verbose_name
#管理画面で表示される文字を変更する。
hoge = models.CharField(max_length=, verbose_name='変更した文字')
一対一(OneToOneField)
column_name = models.OneToOneField([参照先modelクラス名], on_delete=[オプション],[その他オプション])
on_deleteオプションはリレーションシップされているモデルのデータをどのように扱うかを設定します。
種別 | 説明 |
models.CASCADE | データ削除時に参照しているデータも連動して削除(デフォルト設定) |
models.PROTECT | 別モデル(テーブル)から参照させれていると削除できない |
models.RESTRICT | 削除エラーが表示される。片方のデータが削除され、紐づく先のデータは残る |
models.SET_NULL | 参照先のレコードをNullに設定(参照先でNullが許可されている必要あり) |
models.SET_DEFAULT | 参照先のレコードをDefault値に設定(カラムにDefalut値の設定が必要) |
user (id , name ) / address (id , address ) という2つのモデル(テーブル)が存在する場合、addressモデルにOnetoOneFieldを設定するとuser_idというカラムが自動に生成されます。userモデルのidとaddressモデルのuser_idカラムがリレーションされます。
一対多(ForeignKey)
一対多の場合はForeingKeyを使います。一対多のリレーションはテーブルの1つのレコードが他のテーブルの2つ以上とリンクする場合を指します。
一人の人が複数のブログ記事を投稿する、出版社が複数の種類の本を出版しているなどのケースが該当します。
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# ...
自動車会社が複数の車を作っている場合のケースです。
ManufacturerテーブルのidフィールドとCarテーブルに自動生成されたmanufacturer_idフィールドが紐づくようになります。
主キーを自動連番以外に設定する場合
下記は本とショップの2つのモデルを一対多でリレーションする例です。BookCodeは連番ではなく4桁の文字列を使います。
#テーブルA (一側)
class Book(models.Model):
book_code = models.CharField(max_length=4, unique=True, primary_key=True) #主キー・重複なしを設定
name= models.CharField(max_length=50)
def __str__(self):
return '[' + str(self.book_code) + '] ' + str(self.name)
#テーブルB (多側)
class Store(models.Model):
book_code = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='booksStores') #リレーション設定
store_name= models.CharField(max_length=50)
def __str__(self):
return '[' + str(self.Bbook_code) + '] ' + str(self.store_name)
まず、BookモデルにBookCodeカラムを作成し、重複なし・主キーの設定を行います。
StoreモデルでBookCodeカラムにForeignKeyを設定します。on_deleteはBookのデータが消されたときにリレーションしているStoreの情報も自動削除する設定になります。
def __str__(self):
return '[' + str(self.book_code) + '] ' + str(self.store_name)
def __str__(self): は管理画面にデータの内容を表示する設定です。これを設定しないと管理画面で何のデーターがあるのかがわかりません。この例ですと
[本のコード] 本の名前 を表示します。
多対多(MyanyToManyField)
多対多リレーションは特定のテーブルの複数レコードが、他のテーブルの複数レコードと紐づくケースが該当します。
複数のブログ記事に、複数のカテゴリーが登録されている。複数の車に、複数の色が割り当てられている場合などが当てはまります。
ピザとトッピングの2つのテーブルを多対多で関連付けてみます。
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
公式ドキュメントから引用していますが、このケースの場合、Pizzaの方にだけManyToManyFieldが設定されています。Pizza , Topping どちらに定義しても良いですが、どちらか片方にのみ設定するのがルールになっています。また ManyToManyField のフィールド名は関係先モデルのフィールド名の複数形が推奨されています。Pizzaテーブル側に設定するのでToppingテーブルの複数形 toppings をフィールド名として設定します。
多対多の場合、2つのテーブルの他に中間テーブルが設定されます。両方のIDを関連付けて管理するためです。
中間テーブルはcar_pizzaとなり、 id , car_id , pizza_id というフィールドが作られます。
更に複雑な多対多のリレーションは以下のように記載します。詳しい解説はDjango公式ホームページ参照
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through="Membership")
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
データーベースへの反映
まず、models.pyにモデルを定義したら、データベーススキーマに反映させます。まずはマイグレーションを行います。Djangoがモデルに記載された内容を分析し、マイグレーションファイルを作成します。DBに登録する準備を行うと考えるとわかりやすいです。ターミナルから以下のコマンドを実行します。
マイグレーション
$ python manage.py makemigrations
マイグレーションの段階ではDBに変更は何もされません。以下のマイグレートを実行することによりDBに反映されます。こちらもターミナルから下記のコマンドを実行します。
マイグレート
$ python manage.py migrate
マイグレートのロールバック
マイグレートを戻すには、下記のような手順を踏みます。
まず、マイグレーションの一覧を表示します。
$ python manage.py showmigrations AppName
最後にアプリ名を付けるとアプリに関するマイグレーション情報が表示されます。アプリ名を付けないとプロジェクト全体のものが表示されます。
今までDjangoProject初回のマイグレーション、次にCompanyというテーブルを作成、その次にBookというテーブルを作成しています。
今回は3回目に作成したBookというテーブルを削除して、0002の状態に戻してみます。
一つ前の状態を指定するのがポイントです。
$ python manage.py migrate [AppName] [MigrationName]
#記述例) $ python manage.py migrate Sample 0002_company_stockprices
0003番の✗が消えて一つ前の状態に戻りました。
あとはmigrationディレクトリで該当するファイルを削除すれば完了です。
(参考)