Tạo mô hình Django hoặc cập nhật nếu tồn tại


115

Tôi muốn tạo một đối tượng mô hình, như Person, nếu id của người đó không tồn tại, hoặc tôi sẽ lấy đối tượng người đó.

Mã để tạo một người mới như sau:

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

Nhưng tôi không biết kiểm tra và lấy đối tượng người hiện có ở đâu.

Câu trả lời:


169

Nếu bạn đang tìm kiếm trường hợp sử dụng "cập nhật nếu tồn tại, tạo khác", vui lòng tham khảo câu trả lời xuất sắc của @Zags


Django đã có get_or_create, https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create

Đối với bạn nó có thể là:

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

Tôi đang sử dụng django 1.9, và nó đem lại cho tôi: AttributeError: đối tượng 'QuerySet' không có thuộc tính 'update_or_create'
Ofek Gila

1
@OfekGila Đó là lạ, cả mã nguồn và các tài liệu xác nhận QuerySetupdate_or_create
Bakkal

2
Trong trường hợp của tôi, thay cho mã định danh, tôi có một nhóm các trường tạo thành unique_together. Cách sử dụng cho trường hợp này như thế nào?
Rakmo

191

Không rõ câu hỏi của bạn là yêu cầu phương thức get_or_create (có sẵn từ ít nhất Django 1.3) hay phương thức update_or_create (mới trong Django 1.7). Nó phụ thuộc vào cách bạn muốn cập nhật đối tượng người dùng.

Mẫu sử dụng như sau:

# 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 cho update_or_createbởi vì đối với trường hợp sử dụng đó, tốt hơn get_or_createlà chỉ gọi save()lại đối tượng.
bakkal

Trong trường hợp của tôi, thay cho mã định danh, tôi có một nhóm các trường tạo thành unique_together. Cách sử dụng cho trường hợp này như thế nào?
Rakmo

1
Mã định danh @OmkarDeshpande chỉ là một ví dụ; bạn có thể chuyển bất kỳ truy vấn django hợp lệ nào, chẳng hạn nhưPerson.objects.get_or_create(a=a, b=b, c=c, defaults={"name": name})
Zags

Điều gì sẽ xảy ra nếu tôi muốn thêm nhiều trường vào Người đã tạo hơn những trường mặc định?
Lo Bellin

@LoBellin defaultsĐối số cho các hàm này là nơi bạn chỉ định trường nào bạn muốn thêm vào mô hình. Nó không có gì để làm với giá trị mặc định chỉ định trên lĩnh vực mô hình của bạn
Zags

10

Django có hỗ trợ cho việc này, hãy kiểm tra get_or_create

person, created = Person.objects.get_or_create(name='abc')
if created:
    # A new person object created
else:
    # person object already exists

4

Đối với chỉ một số lượng nhỏ các đối tượng, update_or_create hoạt động tốt, nhưng nếu bạn đang thực hiện trên một bộ sưu tập lớn, nó sẽ không mở rộng quy mô tốt. update_or_create đầu tiên luôn chạy một SELECT và sau đó là một 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)

Điều này tốt nhất sẽ chỉ chạy truy vấn cập nhật đầu tiên và chỉ khi nó khớp với 0 hàng thì mới chạy một truy vấn CHÈN khác. Điều này sẽ làm tăng đáng kể hiệu suất của bạn nếu bạn mong đợi hầu hết các hàng thực sự tồn tại.

Tất cả đều phụ thuộc vào trường hợp sử dụng của bạn. Nếu bạn đang mong đợi hầu hết các lần chèn thì có lẽ lệnh Bul_create () có thể là một tùy chọn.


3

Tôi nghĩ rằng tôi sẽ thêm câu trả lời vì tiêu đề câu hỏi của bạn có vẻ như nó đang hỏi cách tạo hoặc cập nhật, thay vì lấy hoặc tạo như mô tả trong nội dung câu hỏi.

Nếu bạn muốn tạo hoặc cập nhật một đối tượng, phương thức .save () đã có hành vi này theo mặc định, từ tài liệu :

Django tóm tắt nhu cầu sử dụng câu lệnh SQL INSERT hoặc UPDATE. Cụ thể, khi bạn gọi save (), Django tuân theo thuật toán này:

Nếu thuộc tính khóa chính của đối tượng được đặt thành giá trị đánh giá là True (tức là giá trị không phải là Không có hoặc chuỗi trống), Django sẽ thực thi CẬP NHẬT. Nếu thuộc tính khóa chính của đối tượng không được đặt hoặc nếu CẬP NHẬT không cập nhật bất kỳ điều gì, Django sẽ thực thi CHÈN.

Điều đáng chú ý là khi họ nói 'nếu CẬP NHẬT không cập nhật bất cứ điều gì' thì về cơ bản họ đang đề cập đến trường hợp id bạn đã cung cấp cho đối tượng chưa tồn tại trong cơ sở dữ liệu.


1

Nếu một trong những đầu vào khi bạn tạo là khóa chính, thì điều này là đủ:

Person.objects.get_or_create(id=1)

Nó sẽ tự động cập nhật nếu tồn tại vì hai dữ liệu có cùng khóa chính không được phép.

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.