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


267

ความแตกต่างระหว่างการรันสองคำสั่งคืออะไร:

foo = FooModel()

และ

bar = BarModel.objects.create()

ไม่คนที่สองทันทีสร้างBarModelในฐานข้อมูลในขณะที่สำหรับFooModelการsave()วิธีการที่จะต้องมีการเรียกอย่างชัดเจนเพื่อเก็บไว้ในฐานข้อมูลหรือไม่


47
ใช่นั่นคือความแตกต่าง
Daniel Roseman

คำตอบ:


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
ฉันไม่เห็นว่าเป็นสิ่งที่ขัดแย้ง โดยทั่วไปแล้วในไพ ธ อนคุณยกตัวอย่างวัตถุโดยใส่เครื่องหมายวงเล็บหลังจากชื่อวัตถุไม่ใช่โดยวิธีการสร้าง
danidee

3
@danidee ฉันเห็นด้วยว่ามันไม่ได้ขัดแย้ง แต่แน่นอนว่ามันทำให้เข้าใจผิด สาเหตุหลักมาจากในลิงก์ของ Nils, example1 คือ "instantiating" แต่ example2 คือ "instantiating + saving" นอกจากนี้ทำไมฉันถึงอ้างถึง "ข้อความค้นหา" doc เมื่อฉันต้องการทราบวิธีบันทึกแบบจำลอง มีความเจ็บปวดมากมายใน django doc
Nakamura

3
@ นากามูระเพราะ INSERT เป็นแบบสอบถามหรือไม่
Juanjo Conti

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มีผลลัพธ์ที่ไม่คาดคิด
Vaibhav Vishal

ไม่ไม่ควร ... แม้ว่าบางฟิลด์จะมีลักษณะแปลก ๆ ใน Django ตัวอย่างเช่นCharFieldแม้ว่าการตั้งค่าnull=Falseจะไม่ทำให้เกิดข้อผิดพลาดหากไม่ได้ระบุไว้: นี่เป็นเพราะ Django ตั้งค่าสตริงโดยค่าเริ่มต้นเป็นสตริงว่าง""ดังนั้นจึงไม่ใช่ในทางเทคนิคnull
Thomas Leonard

ใช่ฉันกำลังมีปัญหาเฉพาะกับตัวอักษรนาและทุ่งนา ใช้obj = MyModel()แล้วobj.full_clean()ตอนนี้
Vaibhav Vishal

10

อัพเดท 15.3.2017:

ฉันได้เปิด Django ฉบับนี้แล้วและดูเหมือนว่าจะเป็นที่ยอมรับเบื้องต้นที่นี่: https://code.djangoproject.com/ticket/27825

ประสบการณ์ของฉันคือเมื่อใช้คลาสConstructor( ORM) โดยการอ้างอิงกับ Django 1.10.5อาจมีความไม่สอดคล้องกันในข้อมูล (เช่นคุณลักษณะของวัตถุที่สร้างขึ้นอาจได้รับประเภทของข้อมูลที่ป้อนเข้าแทนประเภท casted ของคุณสมบัติวัตถุ 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 ให้คำตอบที่ยอดเยี่ยมเกี่ยวกับความรับผิดชอบของนักพัฒนาในการคัดเลือกนักแสดง โปรดอัปเดตคำตอบของคุณ
Artur Barseghyan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.