LoginSignup
0
0

More than 1 year has passed since last update.

Django Reverse accessorエラーの解決方法

Posted at

モデルの作成時に「Revers accessor」というエラーが出たので調べてみました。
エラーが起こる理由と解決方法、解決後の子モデルへの逆参照の方法を書いていきたいと思います。
最初にエラーが起こった状況のモデルを見ていきます。

エラーが起こる状況

自分の場合「Users」モデルと「Notes」モデルを紐付けた時に起こりました。

Usersモデル
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)
Notesモデル
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を付与します。(つけるフィールドはuserfavoritesのどちらでも良い)

Notesモデル
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で行う事ができます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0