パラメータがモデルのリレーションシップ フィールドに追加されるとrelated_name
、パラメータで指定された名前を使用して、逆のリレーションシップを参照できます。以下は、逆の関係を参照する方法を示す簡単な例です。
次の 2 つのモデルがあるとします。
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
上記の例では、Book
モデルには、モデルauthor
に関連する外部キー フィールド があります。パラメーターAuthor
を追加すると、モデルに逆の関係の名前が として与えられます。related_name='books'
Book
books
これで、その逆関係名を使用して、Author
モデルのインスタンス内のそれに関連するオブジェクトのコレクションにアクセスできるようになりますBook
。例えば:
author = Author.objects.get(pk=1)
books = author.books.all()
上記のコードでは、Author
データベースからモデルのインスタンスを取得し、books
逆関係名によってその著者に関連するすべての書籍オブジェクトにアクセスしました。
パラメーターを使用するとrelated_name
、オプションで逆関係の名前を指定して、モデル間を移動し、関連オブジェクトにアクセスできます。
これは、「「多対多」の中間リレーショナル テーブルの逆関係名によって引き起こされる競合を解決するには、逆関係名 (関連名) を使用する」です。
中間リレーションシップ テーブルとは何か、中間リレーションシップ テーブルが存在する理由、および中間リレーションシップ テーブルの逆リレーション名によって引き起こされる競合の詳細な説明については、私の他のテーブル ブログ投稿を参照してください。Django でのデータベース操作メソッドの使用方法を示す実践的な例を通して、ForeignKey()-foreign key in Django [データ テーブル "1 対多" リレーションシップ]、および「中間リレーションシップ テーブル」、逆リレーションシップ (relational_name)、および逆リレーションシップ名の競合の概念を詳しく説明します
。
E:\Python_project\P_001\myshop-test\myshop_background_2\users\models.py のコードは次のとおりです。
from datetime import datetime
from django.db import models
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
SEX = (
(0, '男'),
(1, '女'),
)
LEVEL = (
(1, '寂寞卡会员'),
(2, '钻石卡会员'),
(3, '金卡会员'),
(4, '银卡会员'),
)
STATUS = (
(0, '正常'),
(1, '异常'),
)
truename = models.CharField('真实姓名', blank=True, max_length=50)
mobile = models.CharField('手机号码', max_length=11, default="")
sex = models.IntegerField(default=0, choices=SEX)
birthday = models.DateField(blank=True, null=True)
user_img = models.ImageField("头像", upload_to="user_img", default="")
level = models.IntegerField(default=4, choices=LEVEL)
status = models.IntegerField(default=0, choices=STATUS)
create_time = models.DateTimeField(default=datetime.now, verbose_name='创建时间')
update_time = models.DateTimeField(default=datetime.now, verbose_name="更新时间")
def __str__(self):
return self.username
class Meta(AbstractUser.Meta):
permissions = (
['check_myuser', '审核用户信息'],
)
データベース移行コマンド manage.py makemigrations を実行すると、次のエラーが報告されます。
SystemCheckError: System check identified some issues:
ERRORS:
auth.User.groups: (fields.E304) Reverse accessor for 'auth.User.groups' clashes with reverse accessor for 'users.MyUser.groups'.
HINT: Add or change a related_name argument to the definition for 'auth.User.groups' or 'users.MyUser.groups'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'auth.User.user_permissions' clashes with reverse accessor for 'users.MyUser.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'auth.User.user_permissions' or 'users.MyUser.user_permissions'.
users.MyUser.groups: (fields.E304) Reverse accessor for 'users.MyUser.groups' clashes with reverse accessor for 'auth.User.groups'.
HINT: Add or change a related_name argument to the definition for 'users.MyUser.groups' or 'auth.User.groups'.
users.MyUser.user_permissions: (fields.E304) Reverse accessor for 'users.MyUser.user_permissions' clashes with reverse accessor for 'auth.User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'users.MyUser.user_permissions' or 'auth.User.user_permissions'.
groups
エラー メッセージは、およびフィールドに関する競合を示していますuser_permissions
。
具体的には、 ①auth.User の groups フィールドが users.MyUser のグループと競合する、
② auth.User. の user_permissions フィールドが users.MyUser の user_permissions と競合する、という2 つの競合があります。
質問: auth.User はいつ導入されましたか?
答えは次のコードにあります。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 'basic',
'users',
]
以下のコード内のステートメントに注目してください。
'django.contrib.auth',
質問: 明らかに、モジュールには定義groups
やフィールドがありませんuser_permissions
。
回答: 定義するモデルは、システムに付属するモデルのこれらのフィールドMyUser
を継承し、AbstractUser
継続するため、定義されています。AbstractUser
User
解決:
解決策 1:
アプリケーション 'django.contrib.auth' を settings.py に登録しないでください。ただし、Django 独自のバックグラウンド システムを使用する場合、これは次の理由からお勧めできません: Django では、デフォルトで、アプリケーションは認証とユーザー管理の主要なアプリケーションであり、Django 独自のバックグラウンド管理システムのユーザー認証と権限管理機能を提供し
ますdjango.contrib.auth
。Django 独自のバックエンド管理システムを使用したい場合は、通常、django.contrib.auth
アプリケーションを含める必要があります。
settings.py
アプリケーションを設定にINSTALLED_APPS
含めることで、django.contrib.auth
バックグラウンド管理システムが正常に動作し、ユーザー認証と権限管理の機能が保証されます。このようにして、ユーザー モデル、ユーザー グループ、権限などの組み込み機能を使用できます。
Django 独自のバックグラウンド管理システムを使用したくない場合、またはすでにカスタム ユーザー管理システムを使用している場合はINSTALLED_APPS
、django.contrib.auth
そこからアプリケーションを削除することを検討できます。これにより、不要なコードとデータベース テーブルが削減され、プロジェクトがより軽量になります。
ただし、django.contrib.auth
アプリケーションを削除すると、次のようなユーザー認証と権限に関連する多くの機能が失われることに注意してください。
- ユーザー認証・ログイン機能
- ユーザー登録・パスワードリセット機能
- ユーザー権限と権限管理機能
- ユーザーグループ管理機能
- バックグラウンド管理システムのユーザー認証および権限管理機能
django.contrib.auth
したがって、アプリケーションを削除するかどうかを決定する前に、代替のユーザー認証および権限管理ソリューションがあることを確認し、関連機能の実装とメンテナンスのコストを考慮してください。
解決策 2:
カスタム モデルのgroups
およびフィールドの名前を変更します **:user_permissions
カスタム モデルのgroups
およびフィールドを保持したいが、user_permissions
組み込みモデルとのauth.User
競合を避けたい場合は、related_name
これら 2 つのフィールドにパラメータを追加して、別の名前を指定できます。例えば:
from django.db import models
from django.contrib.auth.models import AbstractUser, Group, Permission
class MyUser(AbstractUser):
# ...
groups = models.ManyToManyField(
Group,
verbose_name='groups',
blank=True,
help_text='The groups this user belongs to.',
related_name='user_groups' # 设置不同的 related_name
)
user_permissions = models.ManyToManyField(
Permission,
verbose_name='user permissions',
blank=True,
help_text='Specific permissions for this user.',
related_name='user_permissions' # 设置不同的 related_name
)
# ...
カスタム モデルのgroups
フィールドとフィールドにパラメーターをuser_permissions
追加し、それらのパラメーターを組み込みモデルのフィールドとは異なる名前related_name
に設定することで、競合を回避できます。auth.User
モデルを変更した後、makemigrations
およびmigrate
コマンドを再度実行して変更を適用する必要があることに注意してください。
python manage.py makemigrations
python manage.py migrate
次の図に示すように、変更が完了した後でコマンド makemigrations を実行すると、エラーは報告されません。