web-dev-qa-db-fra.com

Django: Pourquoi certains champs de modèles se heurtent-ils?

Je veux créer un objet contenant 2 liens vers les utilisateurs. Par exemple:

class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

mais j'obtiens les erreurs suivantes lors de l'exécution du serveur:

  • L'accesseur du champ "cible" se heurte au champ connexe "User.gameclaim_set". Ajoutez un argument related_name à la définition de "cible".

  • L'accesseur du champ "demandeur" se heurte au champ connexe "User.gameclaim_set". Ajoutez un argument related_name à la définition de 'claimer'.

Pouvez-vous expliquer pourquoi je reçois les erreurs et comment les corriger?

168
Oleg Tarasenko

Vous disposez de deux clés étrangères pour l'utilisateur. Django crée automatiquement une relation inverse de l'utilisateur vers GameClaim, qui est généralement gameclaim_set. Cependant, comme vous avez deux FK, vous auriez deux gameclaim_set attributs, ce qui est évidemment impossible. Vous devez donc indiquer Django quel nom utiliser pour la relation inverse.

Utilisez le related_name attribut dans la définition FK. par exemple.

class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()
289
Daniel Roseman

Le modèle User essaie de créer deux champs avec le même nom, un pour le GameClaims qui ont ce User comme target, et un autre pour le GameClaims qui ont ce User comme claimer. Voici les documents sur related_name , qui est la façon dont Django vous permet de définir les noms des attributs afin que ceux générés automatiquement ne soient pas en conflit.

8
Hank Gay

L'OP n'utilise pas une classe de base abstraite ... mais si vous l'êtes, vous constaterez que le codage en dur du nom_connecté dans le FK (par exemple ..., nom_connecté = "myname") entraînera un certain nombre de ces erreurs de conflit - un pour chaque classe héritée de la classe de base. Le lien fourni ci-dessous contient la solution de contournement, qui est simple, mais certainement pas évident.

Depuis les documents Django ...

Si vous utilisez l'attribut related_name sur une ForeignKey ou ManyToManyField, vous devez toujours spécifier un nom inverse unique pour le champ. Cela causerait normalement un problème dans les classes de base abstraites, car les champs de cette classe sont inclus dans chacune des classes enfants, avec exactement les mêmes valeurs pour les attributs (y compris le nom_connecté) à chaque fois.

Plus d'infos ici .

7
Pascal Polleunus

Parfois, vous devez utiliser une mise en forme supplémentaire dans related_name - en fait, à tout moment lorsque l'héritage est utilisé.

class Value(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=5)
    animal = models.ForeignKey(
        Animal, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract = True

class Height(Value):
    pass

class Weigth(Value):
    pass

class Length(Value):
    pass

Pas de conflit ici, mais related_name est défini une fois et Django se chargera de créer des noms de relation uniques.

puis dans les enfants de la classe Value, vous aurez accès à:

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related
2
Sławomir Lenart

En ajoutant simplement à la réponse de Jordan (merci pour l'astuce Jordan), cela peut également se produire si vous importez le niveau au-dessus des applications, puis importez les applications, par exemple.

myproject/ apps/ foo_app/ bar_app/

Donc, si vous importez des applications, foo_app et bar_app, vous pouvez obtenir ce problème. J'avais des applications, foo_app et bar_app, toutes répertoriées dans les paramètres.INSTALLED_APPS

Et vous voulez éviter d'importer des applications de toute façon, car alors vous avez la même application installée dans 2 espaces de noms différents

apps.foo_app et foo_app

0
lukeaus

Il me semble que je rencontre cela de temps en temps lorsque j'ajoute un sous-module en tant qu'application à un projet Django, par exemple étant donné la structure suivante:

myapp/
myapp/module/
myapp/module/models.py

Si j'ajoute ce qui suit à INSTALLED_APPS:

'myapp',
'myapp.module',

Django semble traiter le fichier myapp.mymodule models.py deux fois et renvoie l'erreur ci-dessus. Cela peut être résolu en n'incluant pas le module principal dans la liste INSTALLED_APPS:

'myapp.module',

Inclusion de myapp au lieu de myapp.module provoque la création de toutes les tables de base de données avec des noms incorrects, donc cela semble être la bonne façon de procéder.

Je suis tombé sur ce post en cherchant une solution à ce problème, donc j'ai pensé que je mettrais cela ici :)

0
Jordan Hagan