2009-04-13 1 views
12

Thay vì xóa bản ghi trong ứng dụng Django của tôi, tôi muốn chỉ đánh dấu chúng là "đã xóa" và ẩn chúng khỏi các truy vấn hoạt động của tôi. Lý do chính của tôi để làm điều này là cung cấp cho người dùng tùy chọn phục hồi trong trường hợp họ vô tình xóa bản ghi (các bản ghi này cũng có thể cần thiết cho một số kiểm tra phụ trợ nhất định.)Làm cách nào để tôi có thể dễ dàng đánh dấu các bản ghi bị xóa trong các mô hình Django thay vì xóa chúng?

Có rất nhiều mối quan hệ khóa ngoại, vì vậy khi Tôi đánh dấu một bản ghi là đã xóa Tôi sẽ phải "Cascade" cờ xóa này cho những bản ghi là tốt. Tôi nên sử dụng công cụ, dự án hiện có hoặc phương pháp nào để thực hiện việc này?

Trả lời

11

Django đưa ra khỏi hộp chính xác cơ chế bạn đang tìm kiếm.

Bạn có thể thay đổi người quản lý được sử dụng để truy cập thông qua các đối tượng liên quan. Nếu bạn quản lý tùy chỉnh mới lọc đối tượng trên trường boolean, đối tượng được gắn cờ không hoạt động sẽ không hiển thị trong yêu cầu của bạn.

Xem ở đây để biết thêm chi tiết: http://docs.djangoproject.com/en/dev/topics/db/managers/#using-managers-for-related-object-access

+1

nhưng tôi không tin rằng các tìm kiếm từ các đối tượng khác tôn trọng điều này. tức là nếu bạn tìm kiếm từ một mô hình có liên quan, nó sẽ sử dụng trình quản lý bỏ qua các bản ghi đã xóa. Điều đó có nghĩa là các bản ghi được đánh dấu đã xóa sẽ vẫn còn nguyên vẹn mối quan hệ của chúng - đó có lẽ không phải là những gì bạn muốn. – fastmultiplication

+0

@fastmultiplication Bởi "nó sẽ sử dụng trình quản lý bỏ qua các bản ghi đã xóa", bạn có nghĩa là nó sẽ bỏ qua cờ đã xóa, tức là nó sẽ bao gồm xóa các bản ghi? Đó là hành vi tôi thấy. –

+2

. Sử dụng các trình quản lý để kiểm soát các đối tượng nào có thể truy cập chỉ hoạt động khi bạn sử dụng lớp đó. Nói lớp A đang sử dụng một trình quản lý để ẩn các đối tượng "đã xóa", sau đó 'A.objects' sẽ ẩn các đối tượng đã xóa. Nhưng nếu A liên quan đến lớp B, sau đó 'B.filter (a__name = 'smith')', sẽ tìm kiếm tất cả các đối tượng A, thậm chí cả các đối tượng đã xóa. – fastmultiplication

4

Câu hỏi hay, tôi đã tự hỏi làm thế nào để tự làm điều này một cách hiệu quả.

Tôi không chắc chắn nếu điều này sẽ làm các trick, nhưng django-reversion dường như làm những gì bạn muốn, mặc dù bạn có thể muốn kiểm tra để xem làm thế nào nó đạt được mục tiêu này, như có một số cách không hiệu quả để làm điều đó.

Một ý nghĩ khác là có cờ boolean đáng sợ trên Mô hình của bạn và sau đó tạo trình quản lý tùy chỉnh tự động thêm bộ lọc vào, mặc dù điều này sẽ không hoạt động cho các tìm kiếm trên các Mô hình khác nhau. Tuy nhiên, một giải pháp khác suggested here là có mô hình trùng lặp của tất cả mọi thứ, mà có vẻ như quá mức cần thiết, nhưng có thể làm việc cho bạn. Các ý kiến ​​ở đó cũng thảo luận về các lựa chọn khác nhau.

Tôi sẽ thêm điều đó cho hầu hết các phần tôi không xem xét bất kỳ giải pháp nào đáng để giải quyết rắc rối; Tôi thường chỉ hút nó lên và lọc tìm kiếm của tôi trên cờ boolean. Nó tránh được nhiều vấn đề có thể xảy ra nếu bạn cố gắng quá thông minh. Đó là một nỗi đau và không phải là rất DRY, tất nhiên. Một giải pháp hợp lý sẽ là một hỗn hợp của Trình quản lý tùy chỉnh trong khi nhận thức được các giới hạn của nó nếu bạn thử tìm kiếm một mô hình liên quan thông qua nó.

+0

+1 - Tôi chưa bao giờ nghe nói về dự án này ... tính năng rollback một mình là trêu ngươi nếu đúng! –

+0

django-đảo ngược là mát mẻ, nhưng nó là tuyệt đối overkill trong trường hợp này, bạn không nghĩ? Chúng ta đang nói về việc đảo ngược trạng thái boolean, không quay trở lại một trong nhiều phiên bản được lưu trữ của một đối tượng. – ozan

+0

@ozan: "Tôi sẽ thêm phần lớn vào phần lớn tôi không xem xét bất kỳ giải pháp nào đáng để giải quyết rắc rối." –

3

Tôi nghĩ rằng việc sử dụng cờ 'is_active' boolean là tốt - bạn không cần phải gắn cờ cho các mục có liên quan ở cấp db, bạn chỉ cần tiếp tục tham chiếu đến trạng thái của phụ huynh. Đây là những gì xảy ra với mô hình người dùng của contrib.auth, hãy nhớ - đánh dấu một người dùng không phải là is_active không nhắc django đi qua các mô hình liên quan và cố gắng hủy kích hoạt bản ghi một cách kỳ diệu, thay vào đó bạn chỉ cần kiểm tra thuộc tính is_active của người dùng tương ứng với mục có liên quan.

Ví dụ: nếu mỗi người dùng có nhiều dấu trang và bạn không muốn dấu trang của người dùng không hoạt động hiển thị, chỉ cần đảm bảo rằng bookmark.user.is_active là đúng. Không có nhu cầu cho một lá cờ is_active trên dấu trang.

3

Dưới đây là một blog hướng dẫn nhanh chóng từ Greg Allard từ một vài năm trước đây, nhưng tôi thực hiện nó bằng cách sử Django 1.3 và nó thật tuyệt vời. Tôi đã thêm các phương thức vào các đối tượng của tôi có tên là soft_delete, undelete và hard_delete, đặt self.deleted = True, self.deleted = False và trả về self.delete(), tương ứng.

A Django Model Manager for Soft Deleting Records and How to Customize the Django Admin

0

Có một số gói mà cung cấp chức năng này: https://www.djangopackages.com/grids/g/deletion/

Tôi đang phát triển một https://github.com/meteozond/django-permanent/ Nó thay thế quản lý mặc định và QuerySet xóa các phương pháp để đưa đến việc xóa logic. Nó hoàn toàn đổ bóng mặc định phương pháp xóa Django với một ngoại lệ - nhãn hiệu mô hình được thừa hưởng từ PermanentModel thay vì xóa, ngay cả khi xóa của họ gây ra bởi mối quan hệ.