中学英語811710 views
中学理科1630641 views
ヒストリア290598 views
英語613639 views
小学社会310485 views
世界の国564520 views
MathPython497343 views
小学理科719870 views
教育149510 views
LaTeX962153 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

ForeignKey と OneToOneField でリレーションを作る

データベース設計ではテーブル同士を関連付けることが不可欠です。Django では ForeignKey(多対一)と OneToOneField(一対一)の 2 つのフィールドで、リレーションを Python のクラス属性として表現できます。

ForeignKey(多対一)

「1 つのカテゴリに複数の記事が属する」のような関係が多対一です。ForeignKey を使って、「多」側のモデルに定義します。

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100)

class Article(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    category = models.ForeignKey(
        Category,
        on_delete=models.CASCADE,
        related_name='articles'
    )

Article から Category へのリレーションが作られ、データベースには category_id というカラムが追加されます。on_delete は親レコードが削除されたときの振る舞いを指定する必須パラメータです。

CASCADE

親が削除されたら子も一緒に削除される。最もよく使われる設定。

PROTECT

親に紐づく子が存在する限り、親の削除を禁止する。誤削除を防ぎたいときに有効。

SET_NULL

親が削除されたら子の外部キーを NULL にする。null=True と組み合わせて使う。

SET_DEFAULT

親が削除されたら子の外部キーをデフォルト値にリセットする。default の指定が必要。

ForeignKey を使ったデータの作成と参照

リレーションが定義されていれば、親オブジェクトをそのまま代入できます。

tech = Category.objects.create(name='技術')
article = Article.objects.create(
    title='Django入門',
    body='本文...',
    category=tech
)

# 記事からカテゴリを参照
print(article.category.name)  # '技術'

逆方向のアクセスには related_name で指定した名前を使います。

# カテゴリから記事一覧を参照
tech_articles = tech.articles.all()

related_name を省略すると、Django は article_set という名前を自動生成します。明示的に指定しておく方が可読性は高くなります。

OneToOneField(一対一)

「1 人のユーザーに 1 つのプロフィールが対応する」のような関係が一対一です。内部的には ForeignKeyunique=True を付けたものと同等ですが、逆方向のアクセスが QuerySet ではなくインスタンスを直接返す点が異なります。

from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='profile'
    )
    bio = models.TextField(blank=True)
    avatar_url = models.URLField(blank=True)
ForeignKey

多対一。逆方向アクセスは QuerySet を返す(例: category.articles.all())

OneToOneField

一対一。逆方向アクセスはインスタンスを直接返す(例: user.profile)

OneToOneField を使ったデータの作成と参照

from django.contrib.auth.models import User

user = User.objects.create_user(
    username='alice',
    password='secret123'
)
profile = Profile.objects.create(
    user=user,
    bio='Pythonが好きです'
)

# ユーザーからプロフィールを参照
print(user.profile.bio)  # 'Pythonが好きです'

# プロフィールからユーザーを参照
print(profile.user.username)  # 'alice'

OneToOneField では逆方向のアクセスが .profile のようにインスタンスを直接返します。該当するレコードが存在しない場合は RelatedObjectDoesNotExist 例外が発生するため、hasattr(user, 'profile') で確認するか、例外処理を入れるのが安全です。

ForeignKey の活用パターン

実際のアプリケーションでは、1 つのモデルに複数の ForeignKey を持たせることもあります。

class Comment(models.Model):
    article = models.ForeignKey(
        Article,
        on_delete=models.CASCADE,
        related_name='comments'
    )
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='comments'
    )
    text = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

CommentArticleUser の両方にリレーションを持ちます。「どの記事に対する、誰のコメントか」を 1 つのモデルで表現できるわけです。

リレーションの設計はアプリケーション全体の構造を決定づけます。「1 対多なのか 1 対 1 なのか」を正確に見極めることが、無理のないデータベース設計への第一歩になります。