สร้างโมเดล Django หรืออัปเดตหากมี


115

ฉันต้องการสร้างวัตถุแบบจำลองเช่นบุคคลถ้าไม่มี ID บุคคลนั้นหรือฉันจะได้รับวัตถุบุคคลนั้น

รหัสสำหรับสร้างบุคคลใหม่ดังต่อไปนี้:

class Person(models.Model):
    identifier = models.CharField(max_length = 10)
    name = models.CharField(max_length = 20)
    objects = PersonManager()

class PersonManager(models.Manager):
    def create_person(self, identifier):
        person = self.create(identifier = identifier)
        return person

แต่ฉันไม่รู้ว่าจะตรวจสอบและรับวัตถุบุคคลที่มีอยู่ได้ที่ไหน

คำตอบ:


169

หากคุณกำลังมองหากรณีการใช้งาน "อัปเดตหากมีอยู่อื่นสร้าง" โปรดดูคำตอบที่ยอดเยี่ยมของ @Zags


Django แล้วมีget_or_create, https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create

สำหรับคุณอาจเป็น:

id = 'some identifier'
person, created = Person.objects.get_or_create(identifier=id)

if created:
   # means you have created a new person
else:
   # person just refers to the existing one

ฉันใช้ django 1.9 และให้ฉัน: AttributeError: วัตถุ 'QuerySet' ไม่มีแอตทริบิวต์ 'update_or_create'
Ofek Gila

1
@OfekGila มันแปลกมากทั้งซอร์สโค้ดและเอกสารยืนยันQuerySetมีupdate_or_create
bakkal

2
ในกรณีของฉันแทนตัวระบุฉันมีกลุ่มฟิลด์ที่สร้าง unique_together การใช้งานสำหรับกรณีนี้เป็นอย่างไร?
Rakmo

192

ไม่ชัดเจนว่าคำถามของคุณกำลังถามหาเมธอดget_or_create (มีให้ตั้งแต่ Django 1.3 เป็นอย่างน้อย) หรือวิธีupdate_or_create (ใหม่ใน Django 1.7) ขึ้นอยู่กับว่าคุณต้องการอัพเดตออบเจ็กต์ผู้ใช้อย่างไร

ตัวอย่างการใช้งานมีดังนี้:

# In both cases, the call will get a person object with matching
# identifier or create one if none exists; if a person is created,
# it will be created with name equal to the value in `name`.

# In this case, if the Person already exists, its existing name is preserved
person, created = Person.objects.get_or_create(
        identifier=identifier, defaults={"name": name}
)

# In this case, if the Person already exists, its name is updated
person, created = Person.objects.update_or_create(
        identifier=identifier, defaults={"name": name}
)

12
+1 update_or_createเพราะสำหรับกรณีการใช้งานนั้นดีกว่าget_or_createการเรียกsave()ใช้วัตถุอีกครั้ง
bakkal

ในกรณีของฉันแทนตัวระบุฉันมีกลุ่มฟิลด์ที่สร้าง unique_together การใช้งานสำหรับกรณีนี้เป็นอย่างไร?
Rakmo

1
ตัวระบุ @OmkarDeshpande เป็นเพียงตัวอย่าง คุณสามารถส่งข้อความค้นหา django ที่ถูกต้องได้เช่นPerson.objects.get_or_create(a=a, b=b, c=c, defaults={"name": name})
Zags

จะเกิดอะไรขึ้นถ้าฉันต้องการเพิ่มฟิลด์ให้กับบุคคลที่สร้างขึ้นมากกว่าฟิลด์เริ่มต้น?
Lo Bellin

@LoBellin defaultsอาร์กิวเมนต์ของฟังก์ชันเหล่านี้คือที่ที่คุณระบุฟิลด์ที่คุณต้องการเพิ่มลงในโมเดล ไม่มีส่วนเกี่ยวข้องกับค่าเริ่มต้นที่ระบุไว้ในฟิลด์ของโมเดลของคุณ
Zags


4

สำหรับออบเจ็กต์เพียงเล็กน้อยเท่านั้นupdate_or_create จะทำงานได้ดี แต่ถ้าคุณทำมากกว่าคอลเลกชันขนาดใหญ่มันจะปรับขนาดได้ไม่ดี update_or_createจะรัน SELECT ก่อนเสมอและหลังจากนั้น UPDATE

for the_bar in bars:
    updated_rows = SomeModel.objects.filter(bar=the_bar).update(foo=100)
        if not updated_rows:
            # if not exists, create new
            SomeModel.objects.create(bar=the_bar, foo=100)

สิ่งนี้จะดีที่สุดก็ต่อเมื่อเรียกใช้ update-query แรกและเฉพาะเมื่อตรงกับแถวที่เป็นศูนย์เท่านั้นที่รัน INSERT-query อื่น ซึ่งจะเพิ่มประสิทธิภาพของคุณอย่างมากหากคุณคาดว่าแถวส่วนใหญ่จะมีอยู่จริงๆ

ทั้งหมดนี้ขึ้นอยู่กับกรณีการใช้งานของคุณ หากคุณคาดหวังว่าจะมีการแทรกเป็นส่วนใหญ่บางทีคำสั่งbulk_create ()อาจเป็นตัวเลือก


3

คิดว่าฉันจะเพิ่มคำตอบเนื่องจากชื่อคำถามของคุณดูเหมือนกำลังถามวิธีสร้างหรืออัปเดตแทนที่จะได้รับหรือสร้างตามที่อธิบายไว้ในเนื้อหาคำถาม

หากคุณไม่ต้องการสร้างหรืออัปเดตอ็อบเจ็กต์เมธอด. save () จะมีพฤติกรรมนี้อยู่แล้วโดยค่าเริ่มต้นจากเอกสาร :

Django ระบุความจำเป็นในการใช้คำสั่ง INSERT หรือ UPDATE SQL โดยเฉพาะเมื่อคุณเรียกบันทึก () Django จะทำตามอัลกอริทึมนี้:

หากแอตทริบิวต์คีย์หลักของออบเจ็กต์ถูกตั้งค่าเป็นค่าที่ประเมินเป็น True (เช่นค่าอื่นที่ไม่ใช่ไม่มีหรือสตริงว่าง) Django จะดำเนินการ UPDATE หากไม่ได้ตั้งค่าแอตทริบิวต์คีย์หลักของออบเจ็กต์หรือหากการอัปเดตไม่อัปเดตสิ่งใด Django จะเรียกใช้งาน INSERT

เป็นที่น่าสังเกตว่าเมื่อพวกเขาพูดว่า 'ถ้า UPDATE ไม่อัปเดตอะไร' โดยพื้นฐานแล้วจะอ้างถึงกรณีที่ id ที่คุณให้วัตถุนั้นไม่มีอยู่ในฐานข้อมูล


1

หากหนึ่งในอินพุตที่คุณสร้างเป็นคีย์หลักสิ่งนี้จะเพียงพอ:

Person.objects.get_or_create(id=1)

ระบบจะอัปเดตโดยอัตโนมัติหากมีอยู่เนื่องจากไม่อนุญาตให้ใช้ข้อมูลสองรายการที่มีคีย์หลักเดียวกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.