chọn và cập nhật bản ghi cơ sở dữ liệu với một bộ truy vấn duy nhất


139

Làm cách nào để tôi chạy một updatevà các selectcâu lệnh giống nhau querysetthay vì phải thực hiện hai truy vấn: - một để chọn đối tượng - và một để cập nhật đối tượng

Tương đương trong SQL sẽ là một cái gì đó như:

update my_table set field_1 = 'some value' where pk_field = some_value

Câu trả lời:


266

Sử dụng phương thức đối tượngupdate queryset :

MyModel.objects.filter(pk=some_value).update(field1='some value')

94
Chỉ là một cảnh báo công bằng ... nếu bạn sử dụng updatephương thức như thế này thì mọi tín hiệu được gắn vào mô hình đó hoặc "công cụ mã" khác sẽ không chạy với các đối tượng. Chỉ là một con trỏ từ một người đã bị đốt cháy :)
DMac Kẻ hủy diệt

@DMactheDestroyer anh chàng cảm ơn vì thông tin quý giá đó. Vậy thì chúng ta có nên sử dụng cách cập nhật cũ hơn không? (tức là) có được và tiết kiệm?

@learning tốt anh bạn, tất cả phụ thuộc vào kịch bản của bạn. Các updatephương pháp là rất tốt cho cập nhật tin đại chúng, nhưng nó phải đặt ra một cảnh báo trong đầu của bạn khi bạn sử dụng nó mà bạn cần phải xem xét bất kỳ tín hiệu gắn liền với đối tượng đó cũng có thể cần phải được tự bắn
DMac Destroyer

3
Có thể truy cập thể hiện mô hình hiện tại trong chức năng cập nhật không? thíchMyModel.objects.filter(pk=some_value).update(field1=self.data)
Dipak

8
@DipakChandranP Bạn nên hỏi một câu hỏi mới thay vì đưa ra nhận xét về một đứa trẻ sáu tuổi. Nhưng biểu thức F () có thể muốn bạn muốn.
Daniel Roseman

70

Các đối tượng cơ sở dữ liệu Django sử dụng cùng một phương thức save () để tạo và thay đổi các đối tượng.

obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()

Làm thế nào Django biết CẬP NHẬT so với INSERT
Nếu thuộc tính khóa chính của đối tượng được đặt thành giá trị ước tính là True (nghĩa là một giá trị không phải là Không hoặc chuỗi rỗng), Django thực hiện 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 cứ điều gì, Django sẽ thực thi một INSERT.

Tham khảo: https://docs.djangoproject.com/en/1.9/ref/models/instances/


17

Câu trả lời này so sánh hai cách tiếp cận trên. Nếu bạn muốn cập nhật nhiều đối tượng trong một dòng, hãy truy cập:

# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')

Nếu không, bạn sẽ phải lặp lại bộ truy vấn và cập nhật các đối tượng riêng lẻ:

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. Cách tiếp cận 1 nhanh hơn bởi vì, nó chỉ tạo một truy vấn cơ sở dữ liệu, so với cách tiếp cận 2 tạo ra các truy vấn cơ sở dữ liệu 'n + 1'. (Đối với n mục trong bộ truy vấn)

  2. Cách tiếp cận nắm tay thực hiện một truy vấn db tức là CẬP NHẬT, cách thứ hai thực hiện hai: CHỌN và sau đó CẬP NHẬT.

  3. Sự đánh đổi là, giả sử bạn có bất kỳ trình kích hoạt nào, như cập nhật updated_onhoặc bất kỳ trường nào liên quan như vậy, nó sẽ không được kích hoạt khi cập nhật trực tiếp tức là cách tiếp cận 1.

  4. Cách tiếp cận 1 được sử dụng trên một bộ truy vấn, vì vậy có thể cập nhật nhiều đối tượng cùng một lúc, không phải trong trường hợp của cách tiếp cận 2.


Về 1. - Tôi nghĩ rằng kết quả truy vấn được lưu trữ trong cuộc gọi đầu tiên để truy vấn, do đó thực sự vẫn chỉ là một cuộc gọi đến DB.
dùng2340939

2

Chỉ trong một trường hợp trong serializermọi thứ, bạn có thể cập nhật theo cách rất đơn giản!

my_model_serializer = MyModelSerializer(
    instance=my_model, data=validated_data)
if my_model_serializer.is_valid():

    my_model_serializer.save()

chỉ trong một trường hợp trong formnhững điều!

instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
    form.save()

Tôi nghĩ rằng các bộ nối tiếp là từ Djanog Rest Framework chứ không phải Django thích hợp.
Code-Apprentice

1
Vâng, tuy nhiên Django formlà từ Django thích hợp.
Jamil Noyda
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.