![見出し画像](https://assets.st-note.com/production/uploads/images/83647677/rectangle_large_type_2_8a061de6da4727a005262b3ef3b46d9e.jpeg?width=1200)
Django_models.ForeignObjectとは #230日目
ForeignObjectはForeignKeyの親クラスにもなっているもので、モデル同士で多対一の関係を作ります。特徴として、複数列でテーブル同士を関連づけることが可能です。
先にForeignObjectをフィールドに使ったモデルの記述方法を例示します。「TaskResult」というモデルに、task_idカラムでリレーションしています。
from django_celery_results.models import TaskResult
class Project(models.Model):
name = models.CharField(max_length=255, blank=False)
task_id = models.CharField(max_length=255, null=True)
task_result = models.ForeignObject(TaskResult, null=True, from_fields=(
'task_id',), to_fields=('task_id',), related_name='+', on_delete=models.DO_NOTHING)
ForeignObjectの場合は、ForeignKeyと違ってリレーションのためのカラムを定義しておかなければいけません(task_id)。ただ逆にいうとそこを自由に設定できます。
ソースコードを確認すると、ForeignObjectやForeignKeyはrelatedモジュールに記述されています。
[django/django/db/models/fields/related.py]
class ForeignObject(RelatedField):
"""
Abstraction of the ForeignKey relation, supports multi-column relations.
"""
# Field flags
many_to_many = False
many_to_one = True
one_to_many = False
one_to_one = False
requires_unique_target = True
related_accessor_class = ReverseManyToOneDescriptor
forward_related_accessor_class = ForwardManyToOneDescriptor
rel_class = ForeignObjectRel
def __init__(
self,
to,
on_delete,
from_fields,
to_fields,
rel=None,
related_name=None,
related_query_name=None,
limit_choices_to=None,
parent_link=False,
swappable=True,
**kwargs,
):
~ 略 ~
[django/django/db/models/fields/related.py]
class ForeignKey(ForeignObject):
"""
Provide a many-to-one relation by adding a column to the local model
to hold the remote value.
By default ForeignKey will target the pk of the remote model but this
behavior can be changed by using the ``to_field`` argument.
"""
~ 略 ~
上記で示したProjectモデルに当てはめると、
・toに結合したいテーブルを指定(Projectモデルでは仮引数を省略)
→TaskResult
・to_fieldに結合先のカラムをリストやタプルで指定
→('task_id', )
・from_fieldに結合元 (記述してるモデル)のカラムをリストやタプルで指定
→('task_id', )
to_fieldとfrom_fieldに指定したカラム同士が結びつくことになります。ここでは[None]と指定することも可能で、その場合はpk (primary key)を参照する形になります。
ただ、一見するとForeignKeyではなくForeignObjectを使う理由があまり見当たらず、どういうケースで使われているのか正確には理解できなかったです。
「TaskResult」に対して使われている事例を見たので、、参照先のデータベースがRedisだとForeignKeyが対応していないのかなと勝手に考えています。
ここまでお読みいただきありがとうございました!!
参考
この記事が気に入ったらサポートをしてみませんか?