web-dev-qa-db-fra.com

Django 1.9: Le champ se heurte au champ du champ non existant dans le modèle parent

J'ai quelques modèles simples, Profile, Certifier et Designer, les deux derniers héritant de Profile (héritage multi-tables). Dans Designer, il existe une clé étrangère pour 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)

Dans Django 1.8 cela fonctionne parfaitement, mais dans 1.9 je reçois;

Django.core.management.base.SystemCheckError: SystemCheckError: La vérification du système a identifié certains problèmes:

LES ERREURS:

check.Designer.certifier: (models.E006) Le champ 'certificateur' est en conflit avec le champ 'certificateur' du modèle 'check.profile'.

(Profile.type n'est pas pertinent dans ce cas, j'en ai juste besoin pour distinguer les types de profil utilisateur connectés).

check.profile n'a évidemment pas de champ "certificateur". Est-ce un bug ou ai-je raté quelque chose? La même chose se produit dans un autre projet.

24
Jens-Erik Weber

Je pense que vous ne devriez pas utiliser le certificateur de nom pour cette relation de clé étrangère car la classe Profile a en fait les champs certifier, admin et designer (bien que par descripteur) selon - docs et dans ce cas, les noms s'affronteraient.

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)

Passez à quelque chose comme certifier_field = models.ForeignKey(Certifier)

Comme cela a été souligné dans les commentaires, vous pouvez renommer les modèles en CertifierProfile, AdminProfile, etc. pour éviter le conflit.

Ou vous pouvez aussi mettre le chèque au silence en ajoutant SILENCED_SYSTEM_CHECKS = ['models.E006'] À votre settings, mais ce n'est pas une bonne approche.

20
Alex Polekha

Vous pouvez spécifier que Profile est un classe abstraite . Cela empêchera la vérification d'être confondue avec vos champs parents.

class Meta:
    abstract = True
11
mrcai