web-dev-qa-db-ja.com

Djangoでは `related_name`は何のために使われていますか?

ManyToManyFieldおよびForeignKeyフィールドでrelated_name引数は何に役立ちますか?たとえば、次のコードでは、related_name='maps'の効果は何ですか?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
301
zjm1126

related_name属性は、Userモデルからモデルへの逆方向関係の名前を指定します。

related_nameを指定しない場合、Djangoはモデルの名前に接尾辞_setを付けて自動的に作成します。例えばUser.map_set.all()です。

あなたがを指定した場合、例えばUserモデルのrelated_name=mapsUser.map_setはまだ機能しますが、User.maps.の構文は明らかに少しきれいで、見苦しいです。たとえば、ユーザーオブジェクトcurrent_userがある場合、current_user.maps.all()を使用して、current_userに関連するすべてのMapモデルのインスタンスを取得できます。

詳細は Djangoドキュメント にあります。

403
Wogan

既存の回答に関連する名前を追加することは、同じテーブルを指す2つのFKがモデル内に存在する場合には必須です。例えば部品表の場合

@with_author 
class BOM(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tomaterial =  models.ForeignKey(Material, related_name = 'tomaterial')
    frommaterial =  models.ForeignKey(Material, related_name = 'frommaterial')
    creation_time = models.DateTimeField(auto_now_add=True, blank=True)
    quantity = models.DecimalField(max_digits=19, decimal_places=10)

そのため、このデータにアクセスする必要があるときは、関連名のみを使用できます。

 bom = material.tomaterial.all().order_by('-creation_time')

それは他の方法では動作していません(少なくとも私は同じテーブルに2 FKの場合に関連する名前の使用をスキップすることができませんでした。)

65
Ilya Bibik

related_name引数は、より複雑な関連クラス名がある場合にも役立ちます。たとえば、外部キーの関係があるとします。

class UserMapDataFrame(models.Model):
    user = models.ForeignKey(User) 

関連するUserMapDataFrameからUserオブジェクトにアクセスするためのデフォルトの呼び出しはUser.usermapdataframe_set.all()であり、これを読むのは非常に困難です。

related_nameを使用すると、逆の関係を得るために、より単純で読みやすい名前を指定できます。この場合、user = models.ForeignKey(User, related_name='map_data')を指定すると、呼び出しはUser.map_data.all()になります。

5
Daniel Holmes

関連名パラメータは実際にはオプションです。設定しないと、Djangoは自動的にもう一方のリレーションを作成します。 Mapモデルの場合、Djangoはmap_set属性を作成し、あなたの例ではm.map_set経由でアクセスできるようにします(mはあなたのクラスインスタンスです)。 Djangoが使う式はモデルの名前の後に文字列_setが続きます。したがって、関連するnameパラメータは、新しい動作を提供するのではなく、単にDjangoのデフォルトをオーバーライドします。

2
Abrar