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?


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 .


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

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

Josh Smeaton gab eine ausgezeichnete Antwort bezüglich der Verantwortung des Entwicklers für Cast-Typen. Bitte aktualisieren Sie Ihre Antwort.
Artur Barseghyan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.