Mô hình Django () so với Model.objects.create ()


267

Sự khác biệt giữa việc chạy hai lệnh:

foo = FooModel()

bar = BarModel.objects.create()

Liệu cái thứ hai ngay lập tức tạo ra một BarModelcơ sở dữ liệu, trong khi FooModel, save()phương thức phải được gọi một cách rõ ràng để thêm nó vào cơ sở dữ liệu?


47
Vâng, đó là sự khác biệt.
Daniel Roseman

Câu trả lời:


247

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

Để tạo và lưu một đối tượng trong một bước duy nhất, hãy sử dụng create()phương thức.


3
Các tài liệu django là một chút mâu thuẫn về điểm này theo ý kiến ​​của tôi. Tôi đã có cùng một câu hỏi và đọc "Lưu ý rằng việc khởi tạo một mô hình không có cách nào chạm vào cơ sở dữ liệu của bạn; vì điều đó, bạn cần phải lưu ()." docs.djangoproject.com/en/1.10/ref/models/instances/ triệt
Nils

6
Tôi không thấy điều đó là mâu thuẫn. Nói chung trong python, Bạn khởi tạo các đối tượng bằng cách đặt dấu ngoặc sau tên Đối tượng không theo phương thức tạo
danidee

3
@danidee Tôi đồng ý nó không mâu thuẫn, nhưng chắc chắn là sai lệch. Chủ yếu là vì trong liên kết của Nils, example1 là "tức thời" nhưng example2 là "tức thời + tiết kiệm". Ngoài ra, tại sao tôi nên tham khảo tài liệu "truy vấn" khi tôi muốn biết cách lưu mô hình? Thực sự có rất nhiều đau đớn trong django doc.
Nakamura

3
@Nakamura vì INSERT là truy vấn?
Juanjo Conti

16

Hai cú pháp không tương đương và nó có thể dẫn đến các lỗi không mong muốn. Dưới đây là một ví dụ đơn giản cho thấy sự khác biệt. Nếu bạn có một mô hình:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

Và bạn tạo một đối tượng đầu tiên:

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

Sau đó, bạn cố gắng tạo một đối tượng có cùng khóa chính:

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

vì vậy .create()tạo một đối tượng ngay cả khi một trường bắt buộc ( null=False) bị thiếu? Tôi đang thêm các thử nghiệm vào dự án của mình và createđang có kết quả bất ngờ
Vaibhav Vishal

Không, không nên ... Mặc dù một số loại trường hoạt động hơi kỳ lạ trong Django. Ví dụ: CharFieldngay cả khi được đặt thành null=Falsesẽ không phát sinh lỗi nếu không được cung cấp: điều này là do Django đặt các chuỗi theo mặc định thành một chuỗi trống ""nên về mặt kỹ thuật không phải lànull
Thomas Leonard

vâng, tôi chỉ gặp vấn đề với các trường char và trường trường (về cơ bản cũng là trường char). Sử dụng obj = MyModel(), sau đó obj.full_clean()cho bây giờ.
Vaibhav Vishal

10

CẬP NHẬT 15.3.2017:

Tôi đã mở một vấn đề Django về vấn đề này và dường như nó được chấp nhận sơ bộ tại đây: https://code.djangoproject.com/ticket/27825

Kinh nghiệm của tôi là khi sử dụng lớp Constructor( ORM) bằng các tham chiếu với Django, 1.10.5có thể có một số điểm không nhất quán trong dữ liệu (ví dụ: các thuộc tính của đối tượng được tạo có thể lấy loại dữ liệu đầu vào thay vì kiểu đúc của thuộc tính đối tượng 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 đã đưa ra một câu trả lời xuất sắc liên quan đến trách nhiệm của nhà phát triển đối với các loại diễn viên. Xin vui lòng, cập nhật câu trả lời của bạn.
Artur Barseghyan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.