モデルの作成時に「Revers accessor」というエラーが出たので調べてみました。
エラーが起こる理由と解決方法、解決後の子モデルへの逆参照の方法を書いていきたいと思います。
最初にエラーが起こった状況のモデルを見ていきます。
エラーが起こる状況
自分の場合「Users」モデルと「Notes」モデルを紐付けた時に起こりました。
class Users(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=255)
email = models.EmailField(max_length=255, unique=True)
icon = models.FileField(null=True, upload_to='icon/')
is_staff = models.BooleanField(default=False)
class Notes(models.Model):
title = models.CharField(max_length=255)
content = models.CharField(max_length=500)
tags = models.ManyToManyField(Tag)
favorites = models.ManyToManyField(Users, blank=True)
user = models.ForeignKey('accounts.Users', on_delete=models.CASCADE)
「Users」モデルと「Notes」モデルは一対多の関係にあり、また「Notes」モデルのfavorites
フィールドはユーザーのお気に入り登録をするためのフィールドで「Users」モデルと多対多の関係を持っています。
この「Notes」モデルのように一つのモデルに「Users」モデルと一対多と多対多の関係にあることでエラーが発生します。
なぜエラーが起こるのか?
エラーが起きてしまう原因は「Users」モデルから「Notes」モデルを逆参照する時に「Notes」モデルのuser
フィールドとfavorites
フィールドのどちらを参照すればいいのかわからなくなってしまうからです。
# ユーザーの取得
user = Users.objects.get(pk=1)
# 取得したユーザーのノート取得
notes = user.notes_set.all()
# 取得したユーザーのお気に入りのノート
favorite_notes = user.notes_set.all()
このように「ノートの取得」と「お気に入りの取得」でどちらもuser.notes_set
になってしまいます。
解決方法
このような場合の解決方法は子モデルの方のフィールドにrelated_name
をつける事で解決する事ができます。
今回は「Notes」モデルのfavorites
フィールドにrelated_name
を付与します。(つけるフィールドはuser
とfavorites
のどちらでも良い)
class Notes(models.Model):
title = models.CharField(max_length=255)
content = models.CharField(max_length=500)
tags = models.ManyToManyField(Tag)
favorites = models.ManyToManyField(Users, blank=True, related_name='favorite_notes')
user = models.ForeignKey('accounts.Users', on_delete=models.CASCADE)
「Notes」モデルのfavorites
フィールドにrelated_name='favorite_notes'
をつけました。
このようにする事で「Users」モデルから「Notes」モデルの「favorites」を逆参照する場合はrelated_name
で付けた名前で参照する事ができます。
逆参照の方法
# ユーザーの取得
user = Users.objects.get(pk=1)
# 取得したユーザーのノート取得
notes = user.notes_set.all()
# 取得したユーザーのお気に入りのノート
favorite_notes = user.favorite_notes.all()
「ノートの取得」にはそのままnotes_set
で参照し、「お気に入りの取得」はfavorite_notes
で行う事ができます。