34

Profile、Certifier、および Designer といういくつかの単純なモデルがあり、後者の 2 つは Profile から継承されます (複数テーブルの継承)。Designer には、Certifier への外部キーがあります。

class Profile(models.Model):
    TYPES = (
        ('admin', _('Administrator')),
        ('certifier', _('Certifier')),
        ('designer', _('Designer'))
    )
    
    user = models.OneToOneField(User)
    type = models.CharField(max_length=9, choices=TYPES)
    
    def __str__(self):
        return self.user.username + ' (' + self.type + ')'

class Admin(Profile):
    pass
class Certifier(Profile):
    pass
class Designer(Profile):
    certifier = models.ForeignKey(Certifier)

Django 1.8 ではこれは完全に機能しますが、1.9 では次のようになります。

django.core.management.base.SystemCheckError: SystemCheckError: システム チェックでいくつかの問題が特定されました:

エラー:

check.Designer.certifier: (models.E006) フィールド 'certifier' は、モデル 'check.profile' のフィールド 'certifier' と衝突します。

(この場合、Profile.type は関係ありません。ログインしているユーザー プロファイルの種類を区別するために必要なだけです)。

check.profile には明らかにフィールド「認証者」がありません。これはバグですか、それとも何か見逃していますか? 別のプロジェクトでも同じことが起こります。

4

2 に答える 2

28

その外部キー関係に名前認証者を使用するべきではないと思います。なぜなら、クラス Profile には実際にはcertifieradminおよびdocsdesignerによるフィールド(記述子による)があり、その場合、名前が実際に衝突するからです。

from django.contrib.auth.models import User

c = Certifier.objects.create(
    type='admin',
    user=User.objects.latest('date_joined'),
)

p = c.profile_ptr
print(p.certifier) #username (admin)

のようなものに変更しますcertifier_field = models.ForeignKey(Certifier)

コメントで指摘されているように、衝突を避けるために、モデルの名前を CertifierProfile、AdminProfile などに変更できます。

または、 に追加してチェックを無効にすることもできますが、これは良い方法ではありません。SILENCED_SYSTEM_CHECKS = ['models.E006']settings

于 2015-12-04T11:42:30.077 に答える
23

指定できるProfileのは抽象クラスです。これにより、チェックが親フィールドと混同されるのを防ぎます。

class Meta:
    abstract = True
于 2016-08-08T15:09:05.413 に答える