3 Stimmen

Django RelatedManager's .create() Verwendung?

Ich habe zwei Modelle: Play y PlayParticipant definiert (zum Teil) als:

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

Ein Teil meines Codes hat ein Stück p mit der Kennung 8581, zu der ich gerne Teilnehmer hinzufügen möchte. Ich versuche, die RelatedManager-Funktion zu verwenden. .create() um das zu tun, wie:

p.playparticipant_set.create(player_id=2383)

Daraus konstruiert Django:

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

Ist dies ein Fehler in Django, oder bin ich falsch verwenden .create() ?

Kopieren und Einfügen der Shell zur Überprüfung der Korrektheit:

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`))')

Aus query.log:

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

3voto

oggy Punkte 3303

Ich verstehe nicht, wie Ihr erstes Beispiel ein Fehler sein soll. Dieses Verhalten ist völlig intuitiv. Dein p ist ein spielen mit der ID 2383, und Sie rufen die create-Methode für das zugehörige Set auf. Sie geben auch ein zusätzliches Feld an, das spieler_id und geben ihr den Wert 2383. Es ist nur logisch, dass sowohl die Spiel-ID 2383 ist (weil das die ID des Spiels ist, das diesen verwandten Satz enthält) als auch die Spieler-ID 2383 ist (weil Sie diesen Wert explizit eingegeben haben).

Ihr zweites Beispiel scheint auf einen Fehler hinzuweisen, aber ich kann ihn nicht reproduzieren. Hier sind meine Modelle:

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)

Hier ist die Shell-Ausgabe:

>>> 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

Warum posten Sie dies überhaupt bei SO? Django hat einen Bugtracker, ein paar aktive offizielle Mailinglisten und ein paar IRC-Kanäle.

1voto

ironfroggy Punkte 7655

Sie sollten ein ManyToManyField im Play-Modell verwenden, das sich auf null oder mehr Teilnehmer bezieht. In diesem Code würden Sie einfach Folgendes tun

play.players.add(player)

0voto

Wogan Punkte 63411

Es handelt sich nicht um einen Fehler; überprüfen Sie die Dokumentation insbesondere der Abschnitt über Zusätzliche Felder bei Many-to-many-Beziehungen . Sie legt fest:

Im Gegensatz zu normalen Many-to-many-Feldern können Sie nicht add , create , oder assignment (d.h., beatles.members = [...] ), um Beziehungen zu schaffen.

Die einzige Möglichkeit, diese Art von Beziehung herzustellen, besteht darin, Instanzen des Zwischenmodells zu erstellen.

0voto

Maciej Pasternacki Punkte 2710

Ich kann dieses Verhalten nicht reproduzieren. Mit ähnlichen Modellen kann ich laufen:

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

und ich erhalte eine neue Instanz p de Product , dessen p.manufacturer Fremdschlüssel ist gleich m .

Dies ist auf Django-1.0.2 mit PostgreSQL; welche Version von Django verwenden Sie, und welche SQL-Backend?

Versuchen Sie, zwei neue Minimalmodelle mit einem ForeignKey-Feld zu verwenden, das funktionieren sollte; nähern Sie diese Modelle dann schrittweise an die Modelle an, die das fehlerhafte Verhalten aufweisen. Auf diese Weise können Sie die einzige Änderung isolieren, die das Fehlverhalten verursacht; diese Änderung ist der Schlüssel zur Ursache.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X