Модель Django () проти 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
Документи джанго на мою думку трохи суперечать. У мене виникло те саме питання і я прочитав "Зауважте, що примірник моделі жодним чином не стосується вашої бази даних; для цього вам потрібно зберегти ()." docs.djangoproject.com/en/1.10/ref/models/instance/…
Нілс

6
Я не вважаю це суперечливим. Як правило, в python, ви створюєте інстанціювання об'єктів, ставлячи дужки після назви об'єктів, а не методом створення
danidee

3
@danidee Я погоджуюсь, що це не суперечить, але, безумовно, вводить в оману. Головним чином, через те, що у посиланні Нільса, example1 є "інстанційним", але example2 "інстанційним + збереженням". Крім того, чому я повинен посилатися на документ "запитів", коли хочу знати, як зберегти модель? У django doc дуже багато болів.
Накамура

3
@Nakamura, оскільки 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маю несподівані результати
Вішал,

Ні, не повинно ... Хоча деякі види полів діють на Джанго дещо дивно. Наприклад, CharFieldнавіть якщо встановлено значення null=Falseне призведе до помилки, якщо це не передбачено: це тому, що Джанго встановив рядки за замовчуванням на порожній рядок, ""щоб це не було технічноnull
Томас Леонард

так, у мене виникають проблеми лише з полями char та field field (які в основному є і char char). Використовуючи obj = MyModel(), то obj.full_clean()поки що.
Вішал

10

ОНОВЛЕННЯ 15.3.2017:

Я відкрив випуск про Джанго з цього питання, і, здається, його попередньо прийнято тут: 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

Джош Смітон дав чудову відповідь щодо власної відповідальності розробника за типи акторів. Будь ласка, оновіть свою відповідь.
Артур Барсегян
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.