Question

J'ai deux modèles: Play et PlayParticipant, défini (en partie):

class PlayParticipant(models.Model):
    player = models.ForeignKey('Player')
    play = models.ForeignKey('Play')
    note = models.CharField(max_length=100, blank=True)

Un morceau de mon code a un p de jeu qui a id 8581, et je voudrais ajouter des participants à elle. Je suis en train d'utiliser le .create() de RelatedManager pour le faire, comme:

p.playparticipant_set.create(player_id=2383)

D'où, construit Django:

INSERT INTO `api_playparticipant` (`player_id`, `play_id`, `note`) VALUES (2383, 2383, '')

Est-ce un bogue dans Django, ou suis-je utilise à mauvais escient .create()?

shell copier-coller pour le contrôle de la santé mentale:

In [17]: p = Play.objects.get(id=8581)

In [18]: p.id
Out[18]: 8581L

In [19]: p.playparticipant_set.create(player_id=2383)
...
IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`gc/api_playparticipant`, CONSTRAINT `play_id_refs_id_60804ffd462e0029` FOREIGN KEY (`play_id`) REFERENCES `api_play` (`id`))')

De query.log:

5572 Query       INSERT INTO `api_playparticipant` (`player_id`, `play_id`, `note`) VALUES (2383, 2383, '')
Était-ce utile?

La solution

Je ne vois pas comment est votre premier exemple censé être un bug? Ce comportement est tout à fait intuitive. Votre p est jouer avec un id de 2383, et vous appelez la méthode créer sur son ensemble donné. Vous spécifier aussi un champ supplémentaire, appelé player_id , et en lui donnant une valeur de 2383. Il est logique que les deux id jeu sera 2383 (parce que c'est l'identifiant du jeu contenant cet ensemble connexe) et identification du joueur sera également 2383 (parce que vous avez passé explicitement cette valeur dans).

Votre deuxième exemple semble indiquer un bug, mais je ne peux pas le reproduire. Voici mes modèles:

class Player(models.Model):
    name = models.CharField(max_length=100)

class Play(models.Model):
    title = models.CharField(max_length=100)

class PlayParticipant(models.Model):
    player = models.ForeignKey('Player')
    play = models.ForeignKey('Play')
    note = models.CharField(max_length=100, blank=True)

Voici la sortie du shell:

>>> player1 = Player.objects.create()
>>> player2 = Player.objects.create()
>>> player1.id
2
>>> player2.id
3
>>> play1 = Play.objects.create()
>>> play2 = Play.objects.create()
>>> play1.id
3
>>> play2.id
4
>>> pp1 = play1.playparticipant_set.create(player_id=2)
>>> pp1.play.id
3
>>> pp1.player.id
2

Dans tous les cas, pourquoi vous envoyez des messages à ce SO? Django a un bugtracker, deux listes de diffusion officielles actives et deux canaux IRC.

Autres conseils

Vous devez utiliser un ManyToManyField dans le modèle de lecture qui se rapporte à zéro ou plusieurs participants. Dans ce code, vous serait juste faire

play.players.add(player)

Il est pas un bug; consultez la documentation ; en particulier la section Des champs supplémentaires sur plusieurs à plusieurs relations . Il précise:

  

Contrairement à la normale beaucoup à de nombreux domaines, vous ne pouvez pas utiliser add, create ou assignment (à savoir beatles.members = [...]) pour créer des relations.

     

La seule façon de créer ce type de relation est de créer des instances du modèle intermédiaire.

Je ne peux pas reproduire ce comportement. Avec des modèles similaires, je peux courir:

m = Manufacturer.objects.get(1)
p = m.product_set.create(name='23',category_id=1,price=23,delivery_cost=2)

et je reçois nouvelle instance de p Product, dont p.manufacturer clé étrangère est égale à m.

est sur Django-1.0.2 avec PostgreSQL; la version de Django utilisez-vous, et qui backend SQL?

Essayez d'utiliser deux nouveaux modèles minimaux avec le champ ForeignKey sur l'un d'eux, qui devrait fonctionner; puis faire ces modèles peu à peu plus près des modèles qui présentent le comportement défaillant. De cette façon, vous pouvez isoler seul changement qui le rend mal se comporter; ce changement est la clé de la raison.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top