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

267

Jaka jest różnica między uruchomieniem dwóch poleceń:

foo = FooModel()

i

bar = BarModel.objects.create()

Czy ten drugi od razu tworzy BarModelw bazie danych metodę , podczas FooModelgdy save()metoda musi zostać jawnie wywołana, aby dodać ją do bazy danych?

0leg
źródło
47
Tak, to jest różnica.
Daniel Roseman

Odpowiedzi:

247

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

Aby utworzyć i zapisać obiekt w jednym kroku, użyj create()metody.

Madzohan
źródło
3
Dokumenty django są w tej kwestii nieco sprzeczne. Mam to samo pytanie i przeczytałem „Pamiętaj, że utworzenie modelu w żaden sposób nie wpływa na bazę danych; w tym celu musisz zapisać ()”. docs.djangoproject.com/en/1.10/ref/models/instances/…
Nils
6
Nie uważam tego za sprzeczne. Zasadniczo w Pythonie tworzysz obiekty, umieszczając nawiasy po nazwie obiektów, a nie metodą tworzenia
danidee
3
@danidee Zgadzam się, że nie jest to sprzeczne, ale z pewnością wprowadza w błąd. Głównie dlatego, że w łączu Nilsa przykład1 „tworzy instancję”, ale przykład 2 „tworzy instancję + oszczędza”. Ponadto, dlaczego powinienem odwoływać się do dokumentu „zapytania”, jeśli chcę wiedzieć, jak zapisać model? W Django Doc jest naprawdę dużo bólu.
Nakamura,
3
@Namamura, ponieważ INSERT jest zapytaniem?
Juanjo Conti
16

Dwie składnie nie są równoważne i może prowadzić do nieoczekiwanych błędów. Oto prosty przykład pokazujący różnice. Jeśli masz model:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

I tworzysz pierwszy obiekt:

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

Następnie spróbuj utworzyć obiekt z tym samym kluczem podstawowym:

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
źródło
więc .create()tworzy obiekt, nawet jeśli null=Falsebrakuje wymaganego pola ( )? Dodam testy do mojego projektu i createmam nieoczekiwane wyniki
Vaibhav Vishal
Nie, nie powinno ... Chociaż niektóre typy pól działają trochę dziwnie w Django. Na przykład, CharFieldnawet jeśli ustawione na null=Falsenie spowoduje błędu, jeśli nie zostanie podany: dzieje się tak, ponieważ Django domyślnie ustawia ciągi na pusty, ""więc nie jest to technicznienull
Thomas Leonard
tak, mam problemy tylko z polami znaków i polami pola (które w zasadzie są również polami znaków). Używam obj = MyModel(), więc obj.full_clean()na razie.
Vaibhav Vishal
10

AKTUALIZACJA 15.3.2017:

Otworzyłem problem Django w tej sprawie i wydaje się, że jest wstępnie przyjęty tutaj: https://code.djangoproject.com/ticket/27825

Z mojego doświadczenia wynika, że ​​podczas korzystania z klasy Constructor( ORM) przez odwołania do Django 1.10.5mogą występować pewne niespójności w danych (tzn. Atrybuty tworzonego obiektu mogą uzyskać typ danych wejściowych zamiast rzutowanego typu właściwości obiektu 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
Oleg Belousov
źródło
Josh Smeaton udzielił doskonałej odpowiedzi na temat odpowiedzialności programisty za typy obsady. Zaktualizuj swoją odpowiedź.
Artur Barseghyan