Django Model () vs Model.objects.create ()

267

Was ist der Unterschied zwischen der Ausführung von zwei Befehlen:

foo = FooModel()

und

bar = BarModel.objects.create()

Erstellt die zweite sofort eine BarModelin der Datenbank, während für FooModeldie save()Methode explizit aufgerufen werden muss, um sie der Datenbank hinzuzufügen?

0leg
quelle
47
Ja, das ist der Unterschied.
Daniel Roseman

Antworten:

247

https://docs.djangoproject.com/de/stable/topics/db/queries/#creating-objects

Verwenden Sie die create()Methode , um ein Objekt in einem einzigen Schritt zu erstellen und zu speichern .

Madzohan
quelle
3
Die Django-Dokumente sind meiner Meinung nach in diesem Punkt etwas widersprüchlich. Ich hatte die gleiche Frage und las: "Beachten Sie, dass das Instanziieren eines Modells Ihre Datenbank in keiner Weise berührt. Dazu müssen Sie speichern ()." docs.djangoproject.com/de/1.10/ref/models/instances/…
Nils
6
Ich sehe das nicht als widersprüchlich. Im Allgemeinen instanziieren Sie in Python Objekte, indem Sie nach dem
Objektnamen
3
@danidee Ich stimme zu, es ist nicht widersprüchlich, aber es ist sicherlich irreführend. Hauptsächlich, weil in Nils 'Link Beispiel1 "instanziiert", Beispiel2 "instanziiert + spart". Warum sollte ich mich auch auf das Dokument "Abfragen" beziehen, wenn ich wissen möchte, wie ein Modell gespeichert wird? Es gibt wirklich viele Schmerzen in Django Doc.
Nakamura
3
@ Nakamura weil INSERT eine Abfrage ist?
Juanjo Conti
16

Die beiden Syntaxen sind nicht gleichwertig und können zu unerwarteten Fehlern führen. Hier ist ein einfaches Beispiel, das die Unterschiede zeigt. Wenn Sie ein Modell haben:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

Und Sie erstellen ein erstes Objekt:

foo = Test.objects.create(pk=1)

Anschließend versuchen Sie, ein Objekt mit demselben Primärschlüssel zu erstellen:

foo_duplicate = Test.objects.create(pk=1)
# returns the error:
# django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'PRIMARY'")

foo_duplicate = Test(pk=1).save()
# returns the error:
# django.db.utils.IntegrityError: (1048, "Column 'added' cannot be null")
Thomas Leonard
quelle
so .create()erzeugt ein Objekt , selbst wenn ein erforderliches Feld ( null=False) fehlt? Ich create
füge
Nein, sollte es nicht ... Obwohl einige Feldtypen in Django etwas seltsam wirken. Zum Beispiel, CharFieldselbst wenn auf gesetzt, null=Falsewird kein Fehler ausgelöst, wenn nicht angegeben: Dies liegt daran, dass Django Zeichenfolgen standardmäßig auf eine leere Zeichenfolge gesetzt hat, ""so dass dies technisch nicht der Fall istnull
Thomas Leonard
Ja, ich habe nur Probleme mit Char-Feldern und Field-Feldern (was im Grunde auch Char-Felder sind). Verwenden obj = MyModel(), dann obj.full_clean()für jetzt.
Vaibhav Vishal
10

UPDATE 15.3.2017:

Ich habe ein Django-Problem zu diesem Thema eröffnet und es scheint hier vorläufig akzeptiert zu werden: https://code.djangoproject.com/ticket/27825

Ich habe die Erfahrung gemacht, dass bei Verwendung der Klasse Constructor( ORM) durch Verweise mit Django 1.10.5einige Inkonsistenzen in den Daten auftreten können (dh die Attribute des erstellten Objekts erhalten möglicherweise den Typ der Eingabedaten anstelle des gegossenen Typs der ORM-Objekteigenschaft) ::

models

class Payment(models.Model):
     amount_cash = models.DecimalField()

some_test.py - - object.create

Class SomeTestCase:
    def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
        objs = []
        if not base_data:
            base_data = {'amount_case': 123.00}
        for modifier in modifiers:
            actual_data = deepcopy(base_data)
            actual_data.update(modifier)
            # Hacky fix,
            _obj = _constructor.objects.create(**actual_data)
            print(type(_obj.amount_cash)) # Decimal
            assert created
           objs.append(_obj)
        return objs

some_test.py - - Constructor()

Class SomeTestCase:
    def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
        objs = []
        if not base_data:
            base_data = {'amount_case': 123.00}
        for modifier in modifiers:
            actual_data = deepcopy(base_data)
            actual_data.update(modifier)
            # Hacky fix,
            _obj = _constructor(**actual_data)
            print(type(_obj.amount_cash)) # Float
            assert created
           objs.append(_obj)
        return objs
Oleg Belousov
quelle
Josh Smeaton gab eine ausgezeichnete Antwort bezüglich der Verantwortung des Entwicklers für Cast-Typen. Bitte aktualisieren Sie Ihre Antwort.
Artur Barseghyan