Django Model () против Model.objects.create ()


267

Какая разница между запуском двух команд:

foo = FooModel()

и

bar = BarModel.objects.create()

Второй немедленно создает BarModelв базе данных, в то время FooModelкак save()метод должен вызываться явно, чтобы добавить его в базу данных?


47
Да, это разница.
Даниэль Роузман

Ответы:


247

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

Чтобы создать и сохранить объект за один шаг, используйте create()метод.


3
Django документы немного противоречивы по моему мнению. У меня был тот же вопрос, и я прочитал: «Обратите внимание, что создание экземпляра модели никоим образом не затрагивает вашу базу данных; для этого вам нужно сохранить ()». docs.djangoproject.com/en/1.10/ref/models/instances/…
Нильс

6
Я не считаю это противоречивым. Как правило, в python Вы создаете экземпляры объектов, помещая квадратные скобки после имени объектов, а не методом create
danidee

3
@danidee Я согласен, что это не противоречиво, но, безусловно, вводит в заблуждение. Главным образом потому, что в ссылке Нильса example1 является «созданием экземпляра», а example2 - «создание + сохранение». Кроме того, почему я должен ссылаться на документ «запросы», когда я хочу знать, как сохранить модель? В Django Doc действительно много болей.
Накамура

3
@ Накамура, потому что INSERT - это запрос?
Хуанхо Конти

16

Два синтаксиса не эквивалентны, и это может привести к неожиданным ошибкам. Вот простой пример, показывающий различия. Если у вас есть модель:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

И вы создаете первый объект:

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

Затем вы пытаетесь создать объект с тем же первичным ключом:

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

так .create()создает объект, даже если обязательное поле ( null=False) отсутствует? Я добавляю тесты в свой проект и create
получаю

Нет, не должно ... Хотя некоторые типы полей в Django ведут себя немного странно. Например, CharFieldдаже если установлено значение « null=Falseне», это не вызовет ошибку, если не указано ""null
Томас Леонард

да, у меня проблемы только с полями char и field field (которые в основном тоже char char). Используя obj = MyModel(), тогда obj.full_clean()пока.
Вайбхав Вишал

10

ОБНОВЛЕНИЕ 15.3.2017:

Я открыл Django-проблему по этому вопросу, и она, кажется, предварительно принята здесь: https://code.djangoproject.com/ticket/27825

Мой опыт показывает, что при использовании класса Constructor( ORM) по ссылкам с Django 1.10.5в данных могут быть некоторые несоответствия (т. Е. Атрибуты созданного объекта могут получить тип входных данных вместо приведенного типа свойства объекта 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) дал превосходный ответ относительно собственной ответственности разработчика за типы типов. Пожалуйста, обновите свой ответ.
Артур Барсегян
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.