Tín hiệu Django so với phương pháp lưu ghi đè


89

Tôi đang gặp khó khăn khi xoay đầu với chuyện này. Ngay bây giờ tôi có một số mô hình giống như thế này:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

Đánh giá là có một số "điểm số", điểm tổng thể là trung bình của các điểm số. Khi một bài đánh giá hoặc một điểm số được lưu, tôi cần phải tính toán lại điểm trung bình tổng thể. Hiện tại, tôi đang sử dụng phương pháp lưu bị ghi đè. Có bất kỳ lợi ích nào khi sử dụng bộ điều phối tín hiệu của Django không?

Câu trả lời:


84

Các tín hiệu lưu / xóa thường thuận lợi trong các tình huống mà bạn cần thực hiện các thay đổi không hoàn toàn cụ thể cho mô hình được đề cập hoặc có thể được áp dụng cho các mô hình có điểm chung hoặc có thể được định cấu hình để sử dụng trên các mô hình.

Một nhiệm vụ phổ biến trong savecác phương thức bị ghi đè là tự động tạo ra các sên từ một số trường văn bản trong một mô hình. Đó là một ví dụ về cái gì đó, nếu bạn cần triển khai nó cho một số mô hình, sẽ có lợi khi sử dụng một pre_savetín hiệu, trong đó trình xử lý tín hiệu có thể lấy tên của trường slug và tên của trường để tạo slug từ đó. Khi bạn đã có một cái gì đó như vậy tại chỗ, bất kỳ chức năng nâng cao nào bạn đưa vào cũng sẽ áp dụng cho tất cả các mô hình - ví dụ: tra cứu slug bạn sắp thêm cho loại mô hình được đề cập, để đảm bảo tính duy nhất.

Các ứng dụng có thể tái sử dụng thường được hưởng lợi từ việc sử dụng các tín hiệu - nếu chức năng mà chúng cung cấp có thể được áp dụng cho bất kỳ mô hình nào, thì nói chung (trừ khi không thể tránh khỏi), họ sẽ không muốn người dùng phải trực tiếp sửa đổi mô hình của họ để hưởng lợi từ nó.

Ví dụ: với django-mptt , tôi đã sử dụng pre_savetín hiệu để quản lý một tập hợp các trường mô tả cấu trúc cây cho mô hình sắp được tạo hoặc cập nhật và pre_deletetín hiệu để loại bỏ chi tiết cấu trúc cây cho đối tượng đang bị xóa và toàn bộ cây con của các đối tượng trước nó và chúng bị xóa. Do việc sử dụng các tín hiệu, người dùng không phải thêm hoặc sửa đổi savehoặc deletecác phương pháp trên mô hình của họ để thực hiện việc quản lý này cho họ, họ chỉ cần cho django-mptt biết họ muốn nó quản lý mô hình nào.


Điều gì sẽ xảy ra nếu trình xử lý tín hiệu kích hoạt một ngoại lệ? Tôi cho rằng họ không nên kích hoạt các trường hợp ngoại lệ, nếu không thì họ không phù hợp. Tôi có lầm không?
x-yuri

20

Bạn đã hỏi:

Có bất kỳ lợi ích nào khi sử dụng bộ điều phối tín hiệu của Django không?

Tôi tìm thấy cái này trong tài liệu django:

Các phương thức mô hình ghi đè không được gọi trên các hoạt động hàng loạt

Lưu ý rằng phương thức delete () cho một đối tượng không nhất thiết phải được gọi khi xóa hàng loạt đối tượng bằng QuerySet hoặc do kết quả của việc xóa theo tầng. Để đảm bảo logic xóa tùy chỉnh được thực thi, bạn có thể sử dụng tín hiệu pre_delete và / hoặc post_delete.

Thật không may, không có cách giải quyết nào khi tạo hoặc cập nhật hàng loạt đối tượng, vì không có lệnh save (), pre_save và post_save nào được gọi.

Từ: Ghi đè các phương pháp mô hình xác định trước


3
Chế độ xem danh sách quản trị viên Django sử dụng tính năng xóa hàng loạt ... đã bị nhầm lẫn cho đến khi tình cờ gặp được mẩu tin này.
N.Balauro

7
nó cũng cho biết "Rất tiếc, không có cách giải quyết nào khi tạo hoặc cập nhật hàng loạt đối tượng, vì không có lệnh nào trong số save (), pre_save và post_save được gọi." - vì vậy tôi không nghĩ đây là sự cân bằng giữa các phương pháp này.
Cory

Điều này áp dụng cho cả hai phương pháp, vì vậy câu trả lời sau đó là: "không, không có lợi gì khi sử dụng các tín hiệu trái ngược với việc ghi đè savephương thức"?
Flimm

3

Nếu bạn sử dụng các tín hiệu, bạn sẽ có thể cập nhật Điểm đánh giá mỗi khi mô hình điểm liên quan được lưu. Nhưng nếu không cần chức năng như vậy, tôi không thấy có lý do gì để đưa điều này vào tín hiệu, đó là thứ khá liên quan đến mô hình.



1

Bổ sung nhỏ từ tài liệu Django về xóa hàng loạt ( .delete()phương pháp trên QuerySetcác đối tượng):

Hãy nhớ rằng điều này, bất cứ khi nào có thể, sẽ được thực thi hoàn toàn trong SQL và do đó, các phương thức delete () của các cá thể đối tượng riêng lẻ sẽ không nhất thiết phải được gọi trong quá trình này. Nếu bạn đã cung cấp phương thức delete () tùy chỉnh trên một lớp mô hình và muốn đảm bảo rằng nó được gọi, bạn sẽ cần xóa các phiên bản của mô hình đó "theo cách thủ công" (ví dụ: bằng cách lặp lại QuerySet và gọi delete () trên từng đối tượng riêng lẻ) thay vì sử dụng phương thức delete () hàng loạt của QuerySet.

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

Và cập nhật hàng loạt ( .update()phương pháp trên QuerySetcác đối tượng):

Cuối cùng, hãy nhận ra rằng update () thực hiện cập nhật ở cấp SQL và do đó, không gọi bất kỳ phương thức save () nào trên các mô hình của bạn, cũng như không phát ra các tín hiệu pre_save hoặc post_save (là hệ quả của việc gọi Model.save ( )). Nếu bạn muốn cập nhật một loạt các bản ghi cho một mô hình có phương thức save () tùy chỉnh, hãy lặp lại chúng và gọi save ()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update


Điều này không áp dụng cho cả hai?
Flimm
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.