モデルとは、DBにアクセスしてテーブルの作成や、データの取得、更新、挿入を行うものになります。
今回は、このモデルの基本的な使い方や、CRUD操作、テーブル間の紐づけ方法など見ていきたいと思います。
Modelの使い方
テーブルの作成
アプリディレクトリ(my_app)の中の「models.py」にモデルの設定を書きます。
from django.db import models
# Create your models here.
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
この例では以下のような意味になります。
・Person というモデルを作成
・first_name と last_name というカラムを作成
・それぞれのカラムのデータ型に「CharField」を指定
(データ型の種類は以下を参照)
https://docs.djangoproject.com/ja/3.1/ref/models/fields/#model-field-types
ではこのモデルを元に、マイグレーションファイルを作成します。
以下のコマンドを実行します。
python manage.py makemigrations my_app --name add_person
すると、「/my_app/migrations」の中に「0001_add_person.py」というファイルが作成されます。
ではマイグレーションを実行します。
python manage.py migrate my_app
すると、SQLite にテーブルが作成されているのが確認できます。

新しくモデルを追加するときも、同様に「models.py」に追記しコマンドを実行します。
from django.db import models
# Create your models here.
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class Sales(models.Model):
fee = models.IntegerField()
python manage.py makemigrations my_app --name add_sales
python manage.py migrate my_app

マイグレーションの巻き戻し
現時点で、以下の2つのマイグレーションが実行されています。
・0001_add_person.py
・0002_add_sales.py
0002_add_sales のマイグレーションを無かったことにして、
0001_add_person の地点に戻したい場合、以下のコマンドを実行します。
python manage.py migrate my_app 0001_add_person
すると、「my_app_sales」というテーブルが削除されています。
ちなみに、マイグレーションを全て無効にしたい場合は、以下のコマンドになります。
python manage.py migrate my_app zero
マイグレーション状況の確認
以下のコマンドを実行します。
python manage.py showmigrations my_app
すると以下のように表示され、×マークがマイグレーション実行済みを表しています。

admin画面の使用
「admin.py」を以下のように書きます。
from django.contrib import admin
from .models import Person
# Register your models here.
admin.site.register(Person)
以下のコマンドを実行します。
python manage.py createsuperuser
ユーザー名、メールアドレス、パスワードを聞かれるので入力します。
その後、ブラウザで「/admin」にアクセスすると、
以下の画面が表示されるのでログインします。

すると、以下の画面に移るので、Person の「追加」を押します。

任意の名前を入力して保存します。

すると、データベースに反映されているのが確認できます。

Model に Meta属性を追加
class Meta を使うことで、Model全体 に Meta属性を追加することができます。
では、いったんマイグレーションを全て無効にし、マイグレーションファイルも削除します。
python manage.py migrate my_app zero
そして、「models.py」を以下のように修正します。
from django.db import models
from django.utils import timezone
# Create your models here.
class Base(models.Model):
created_at = models.DateTimeField(default=timezone.datetime.now)
updated_at = models.DateTimeField(default=timezone.datetime.now)
class Meta:
abstract = True
class Person(Base):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class Meta:
db_table = 'person'
index_together = [['first_name', 'last_name']]
Base という抽象クラスを定義し、Person クラスに継承しています。
(Meta 属性の種類に関しては以下を参照)
https://docs.djangoproject.com/ja/3.1/ref/models/options/
下記コマンドでマイグレーションを実行します。
python manage.py makemigrations my_app --name add_person
python manage.py migrate my_app
作成されたマイグレーションファイルを確認すると、options に先ほど設定したMeta属性が反映されているのがわかります。
migrations.CreateModel(
name='Person',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(default=datetime.datetime.now)),
('updated_at', models.DateTimeField(default=datetime.datetime.now)),
('first_name', models.CharField(max_length=30)),
('last_name', models.CharField(max_length=30)),
],
options={
'db_table': 'person',
'index_together': {('first_name', 'last_name')},
},
),
CRUD操作
モデルを使用したCRUD操作のやり方をみていきます。
適当なファイルにデータベースを操作するための記述を書き、
そのファイルを実行するという流れになります。
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'プロジェクトディレクトリ.settings')
from django import setup
setup()
from my_app.models import Person
# ここから下にCRUD操作を書く
データの追加
save()メソッド
以下のように、インスタンスに対して save()メソッドを実行することで、データを追加できます。
person = Person(
first_name='taro',
last_name='yamada'
)
person.save()
create()メソッド
以下のように、クラスの create()メソッドを実行することで、データを追加できます。
Person.objects.create(
first_name='jiro',
last_name='sato'
)
get_or_create()メソッド
create()メソッドと使い方は同じですが、
保存するカラムが全て同じであるデータがすでにある場合は、データの追加が行われません。
# 保存されない
Person.objects.get_or_create(
first_name='taro',
last_name='yamada'
)
# 保存される
Person.objects.get_or_create(
first_name='taro',
last_name='yamada',
created_at = '3000-01-01 00:00:00.000000'
)
データの取得
all()メソッド
データをすべて取得することができます。
people = Person.objects.all()
get()メソッド
データをひとつだけ取得する場合に用います。
検索条件に複数のデータが合致する場合や、ひとつも存在しない場合はエラーになります。
person = Person.objects.get(pk=1)
filter()メソッド
検索条件に一致するデータを全て取得します。
複数でもエラーになりません。
people = Person.objects.filter(first_name='taro').all()
データの更新
save()メソッド
データを更新後、save()メソッドで変更を保存することができます。
person = Person.objects.get(id=1)
person.first_name = 'hiroshi'
person.save()
update()メソッド
複数のデータを一度に更新する場合はこちらのメソッドを使用します。
Person.objects.filter(first_name='taro').update(
first_name = 'hiroshi'
)
データの削除
データの削除には、delete()メソッドを使用します。
# 特定のデータだけ削除
Person.objects.filter(first_name='jiro').delete()
# 全て削除
Person.objects.all().delete()
テーブル間のひもづけ
一対多の関係
ここでは、都道府県と学校と生徒を例に「一対多の関係」のひもづけをみていきます。
モデルの作成
「models.py」に新しくモデルを3つ追加します。
.
.
.
class Student(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
major = models.CharField(max_length=20)
school = models.ForeignKey(
'School', on_delete=models.CASCADE
)
class Meta:
db_table = 'students'
class School(models.Model):
name = models.CharField(max_length=20)
prefecture = models.ForeignKey(
'Prefecture', on_delete=models.CASCADE
)
class Meta:
db_table = 'schools'
class Prefecture(models.Model):
name = models.CharField(max_length=20)
class Meta:
db_table = 'prefectures'
ForeignKey で外部キーを設定することができます。
「on_delete=models.CASCADE」と指定すると、参照先のデータが削除されたときにこのデータも削除されるように設定できます。
マイグレーションを実行
python manage.py makemigrations my_app --name add_student_school_prefecture
python manage.py migrate my_app
データベースを確認すると、students テーブルに「school_id」という外部キーが自動的に生成されています。

データの追加
適当なファイルに以下を記述して実行します。
import os
import random
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'プロジェクトディレクトリ.settings')
from django import setup
setup()
from my_app.models import Student, School, Prefecture
prefectures = ['大阪府', '愛知県', '東京都']
schools = ['東高校', '西高校', '南高校', '北高校']
students = ['太郎', '次郎', '三郎', '四郎']
def insert_records():
for prefecture_name in prefectures:
prefecture = Prefecture(
name = prefecture_name
)
prefecture.save()
for school_name in schools:
school = School(
name = f'{prefecture_name}立{school_name}',
prefecture = prefecture
)
school.save()
for student_name in students:
student = Student(
name = student_name,
age = random.randrange(15, 19),
school = school
)
student.save()
insert_records()
結合先データの取得
ForeignKey フィールドがある側:
「インスタンス.フィールド名」で取得
ForeignKey フィールドがない側:
「インスタンス.フィールド名_set.all()」で取得
# ForeignKey フィールドがある側
student1 = Student.objects.first()
print(student1.school)
# ForeignKey フィールドがない側
school1 = School.objects.first()
print(school1.student_set.all())
一対一の関係
ここでは、学校と校長先生を例に「一対一の関係」のひもづけをみていきます。
モデルの作成
ここまでですでに作ったテーブルを削除して新しくモデルを作り直します。
from django.db import models
class School(models.Model):
name = models.CharField(max_length=20)
class Meta:
db_table = 'schools'
class HeadTeacher(models.Model):
school = models.OneToOneField(
School,
on_delete=models.CASCADE,
primary_key=True
)
name = models.CharField(max_length=50)
class Meta:
db_table = 'head_teachers'
一対一の関係のときは、外部キーをプライマリキーとすることができます。
school = models.OneToOneField(
School,
on_delete=models.CASCADE,
primary_key=True
)
そして、マイグレーションを実行してテーブルを作成します。
データの追加
適当なファイルに以下を記述して実行します。
import os
import random
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'プロジェクトディレクトリ.settings')
from django import setup
setup()
from my_app.models import School, HeadTeacher
schools = ['東高校', '西高校', '南高校', '北高校']
head_teachers = ['鈴木先生', '佐藤先生', '高橋先生']
def insert_records():
for school_name in schools:
school = School(
name = school_name
)
school.save()
for head_teacher_name in head_teachers:
head_teacher = HeadTeacher(
school = school,
name = head_teacher_name
)
head_teacher.save()
insert_records()
データ挿入後、head_teachers テーブルを確認すると、以下のように「高橋先生」しか存在しないのがわかります。

これは、学校と校長が「一対一の関係」と指定しているため上書きしているわけですね。
結合先データの取得
ForeignKey フィールドがある側もない側も、
「インスタンス.フィールド名」で取得できます。
多対多の関係
ここでは、生徒とクラブを例に「多対多の関係」のひもづけをみていきます。
モデルの作成
.
.
.
class Club(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Meta:
db_table = 'clubs'
class Student(models.Model):
name = models.CharField(max_length=50)
clubs = models.ManyToManyField(Club)
def __str__(self):
return self.name
class Meta:
db_table = 'students'
これでマイグレーションを実行すると、「students_clubs」というテーブルが自動的に作成され、2つのテーブルを結びつけるためのカラムを持ちます。

データの追加
適当なファイルに以下を記述して実行します。
import os
import random
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'プロジェクトディレクトリ.settings')
from django import setup
setup()
from my_app.models import Student, Club
def insert_students():
student1 = Student(name='太郎')
student2 = Student(name='次郎')
student3 = Student(name='三郎')
student1.save()
student2.save()
student3.save()
def insert_clubs():
club1 = Club(name='サッカー部')
club2 = Club(name='ダンス部')
club3 = Club(name='軽音部')
club1.save()
club2.save()
club3.save()
# データの挿入
insert_students()
insert_clubs()
# 生徒とクラブのひもづけ
student1 = Student.objects.get(pk=1)
club1 = Club.objects.get(pk=1)
club2 = Club.objects.get(pk=2)
student1.clubs.add(club1, club2)
students_clubs テーブルを見ると、以下のように紐づけられていることがわかります。

結合先データの取得
ForeignKey フィールドがある側:
「インスタンス.フィールド名.all()」で取得
ForeignKey フィールドがない側:
「インスタンス.フィールド名_set.all()」で取得
# 生徒とクラブのひもづけ
student1 = Student.objects.get(pk=1)
club1 = Club.objects.get(pk=1)
club2 = Club.objects.get(pk=2)
student1.clubs.add(club1, club2)
# 紐づいているデータの取得
# ForeignKey フィールドがある側
print(student1.clubs.all())
# ForeignKey フィールドがない側
print(club1.student_set.all())
レコードの絞り込み
以下の公式を参照
クエリを作成する | Django ドキュメント | Django (djangoproject.com)
今回は以上になります。
ご覧いただきありがとうございました!
続きはこちら↓
コメント