2010-12-23 5 views
11

Ich habe eine Methode, die funktioniert, aber es scheint sehr ungeschickt, und ich würde denken, es gibt einen besseren Weg, dies zu tun.Instanziieren Modellinstanz mit vielenTomany Feld in Django

Ich habe ein Modell, das einen Benutzer auf meiner Website (ein Twitter-Klon für Lernzwecke) mit einer Liste anderer Benutzer in Beziehung setzt.

Wenn ich jetzt einen neuen Benutzer erstelle, möchte ich diese Liste mit dem Benutzer als Mitglied der Liste initialisieren.

mein Modell ist:

class FollowerList(models.Model) 
    follower = models.ForeignKey(User,related_name="follower") 
    followed = models.ManyToManyField(User,related_name="followed" 

den Code in meiner Ansicht, dass ich gerade jetzt bin ist

user = User.objects.get(username=uname) 
flst = FollowerList() 
flst.follower = user 
flst.save() 
flst.followed.add(user) 
flst.save() 

Es scheint mir, wie es sollte ein Verfahren sein, das für die Erstellung von ohne save() zweimal aufzurufen, aber ich kann es nicht in der Dokumentation oder anderswo finden.

Antwort

12

Sie brauchen nicht nach dem many2many.add speichern() aufzurufen

Sie auch den Code zu 2 Zeilen verkürzen könnte: Antwort

flst = FollowerList.objects.create(follower=user) 
flst.followed.add(user) 
+0

Das Problem, wenn ich dies tun, ist, dass ich eine Fehlermeldung erhalten dass FollowerList Objekt ein Muss Primärschlüssel, bevor es die ManyToManyField-Instanzen hinzufügen kann. Und der einzige Weg, den ich sehen kann, ist, ihn zuerst zu instantiieren und zu speichern und dann das andere Feld hinzuzufügen. –

+0

Nun, FollowerList.objects.create (Follower = Benutzer) gibt es einen Primärschlüssel. Es macht das Speichern. –

+0

Gibt es einen Link zu Dokumenten zu diesem Thema? Kann keine finden ... – jperelli

4

Yuji ist richtig. Sie können ein Objekt erst dann zum M2M-Feld hinzufügen, wenn es gespeichert wurde. Ich möchte jedoch einen kürzeren Weg zum Erstellen von Instanzen nennen.

Ich finde diese Syntax etwas schöner als das Erstellen einer leeren Instanz und das Zuweisen von Feldern. Obwohl die von Yuki erwähnte Methode objects.create() noch schöner ist.

2

Eine späte Antwort auf diese: Sie auch den Konstruktor überschreiben könnte (__init__) wie folgt:

class FollowerList(models.Model): 
    follower = models.ForeignKey(User,related_name="follower") 
    followed = models.ManyToManyField(User,related_name="followed" 

    def __init__(*args, followed=[], **kwargs): 
     super(FollowerList, self).__init__(*args, **kwargs) 
     self.save() 
     for user in followed: 
      self.followed.add(user) 
hier

also habe ich behandelt ausdrücklich die followed Schlüsselwort-Argument in der __init__ Funktion, während alle vorbei andere args und kwargs auf den Standardkonstruktor. Der Aufruf an save stellt sicher, dass das Objekt registriert wurde und somit in einer m2m-Beziehung verwendet werden kann.

Somit können Sie FollowerList mit einer Zeile erzeuge, zB

flst = FollowerList(follower=user, followed=[user,]) 

Alternativ kann, wie von Johannes wies darauf hin, ein Modell in der __init__ Speichern ist nicht zu erwarten. Der bevorzugte Ansatz wäre eine Manager Methode zu schaffen - siehe hier für weitere Details: https://docs.djangoproject.com/en/1.9/topics/db/managers/ und dann eine erstellen FollowerList:

fl = FollowerList.objects.create(*args, followed, **kwargs) 
+1

nicht wirklich sicher, wenn das Speichern des Modells in der init-Methode eine gute Idee ist. Ich würde nicht erwarten, dass dies passiert, wenn ich eine Instanz eines neuen Objekts erstelle (wenn ich es direkt in der Datenbank speichern möchte, rufe ich lieber objects.create() auf) –