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


267

Qual è la differenza tra l'esecuzione di due comandi:

foo = FooModel()

e

bar = BarModel.objects.create()

Il secondo crea immediatamente un BarModelnel database, mentre per FooModel, il save()metodo deve essere chiamato esplicitamente per aggiungerlo al database?


47
Sì, questa è la differenza.
Daniel Roseman,

Risposte:


247

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

Per creare e salvare un oggetto in un solo passaggio, utilizzare il create()metodo


3
I documenti di django sono un po 'contraddittori su questo punto secondo me. Ho avuto la stessa domanda e ho letto "Nota che l'istanza di un modello non tocca in alcun modo il tuo database; per questo, devi salvare ()." docs.djangoproject.com/en/1.10/ref/models/instances/…
Nils

6
Non lo vedo contraddittorio. Generalmente in Python, istanziate oggetti mettendo parentesi dopo il nome Oggetti non con un metodo di creazione
danidee

3
@danidee Concordo sul fatto che non è contraddittorio, ma è certamente fuorviante. Principalmente perché nel link di Nils, example1 sta "istanziando" ma example2 sta "istanziando + salvando". Inoltre, perché dovrei fare riferimento al documento "query" quando voglio sapere come salvare un modello? Ci sono davvero molti dolori nel django doc.
Nakamura,

3
@Nakamura perché INSERT è una query?
Juanjo Conti,

16

Le due sintassi non sono equivalenti e possono portare a errori imprevisti. Ecco un semplice esempio che mostra le differenze. Se hai un modello:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

E crei un primo oggetto:

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

Quindi si tenta di creare un oggetto con la stessa chiave primaria:

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

quindi .create()crea un oggetto anche se null=Falsemanca un campo obbligatorio ( )? Sto aggiungendo dei test al mio progetto e sto createottenendo risultati inaspettati
Vaibhav Vishal,

No, non dovrebbe ... Anche se alcuni tipi di campo si comportano in modo un po 'strano in Django. Ad esempio, CharFieldanche se impostato su null=Falsenon genererà un errore se non fornito: questo perché Django imposta le stringhe per impostazione predefinita su una stringa vuota, ""quindi non è tecnicamentenull
Thomas Leonard

sì, sto avendo problemi solo con i campi char e field field (che è fondamentalmente anche campo char). Usando obj = MyModel(), quindi obj.full_clean()per ora.
Vaibhav Vishal,

10

AGGIORNAMENTO 15.3.2017:

Ho aperto un problema di Django su questo e sembra essere accettato in via preliminare qui: https://code.djangoproject.com/ticket/27825

La mia esperienza è che quando si utilizza la classe Constructor( ORM) mediante riferimenti con Django 1.10.5potrebbero esserci alcune incongruenze nei dati (ad esempio, gli attributi dell'oggetto creato potrebbero ottenere il tipo di dati di input anziché il tipo cast della proprietà dell'oggetto ORM) :

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 ha dato un'ottima risposta per quanto riguarda la responsabilità dello sviluppatore nei confronti dei tipi di cast. Per favore, aggiorna la tua risposta.
Artur Barseghyan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.