Tôi có loại hệ thống như thế này trên một dự án mà tôi vừa mới hoàn thành. Sẽ có rất nhiều công việc để kết hợp với nhau, nhưng đây là một số thành phần mà tôi phải làm cho hệ thống của mình hoạt động:
Bạn cần một cách để xác định Trình chỉnh sửa và Giám sát. Ba cách này có thể được thực hiện là 1.) bằng cách có một trường M2M xác định Giám sát [và giả định rằng mọi người khác có quyền đọc/ghi là một Editor], 2.) tạo 2 mô hình Người dùng mới kế thừa từ Người dùng [ có lẽ nhiều việc hơn cần thiết] hoặc 3.) sử dụng khả năng django.auth để có một lớp UserProfile. Phương pháp số 1 có lẽ là hợp lý nhất.
Khi bạn có thể xác định loại người dùng là gì, bạn cần một cách để thực thi chung ủy quyền mà bạn đang tìm kiếm. Tôi nghĩ tuyến đường tốt nhất ở đây có lẽ là mô hình quản trị chung.
Cuối cùng, bạn sẽ cần một số kiểu "cha mẹ" sẽ giữ quyền cho bất kỳ điều gì cần được kiểm duyệt. Ví dụ, nếu bạn có một mô hình Blog và mô hình BlogPost (giả sử nhiều blog trong cùng một trang), thì Blog là mô hình gốc (nó có thể giữ quyền của người phê duyệt cái gì). Tuy nhiên, nếu bạn có một blog duy nhất và không có mô hình gốc cho BlogPost, chúng tôi sẽ cần một số nơi để lưu trữ quyền. Tôi đã tìm thấy các ContentType
hoạt động tốt ở đây.
Dưới đây là một số ý tưởng về mã (chưa được kiểm chứng và mang tính khái niệm hơn thực tế).
Tạo một ứng dụng mới có tên 'được kiểm duyệt' sẽ giữ nội dung chung của chúng tôi.
moderated.models.py
class ModeratedModelParent(models.Model):
"""Class to govern rules for a given model"""
content_type = models.OneToOneField(ContentType)
can_approve = models.ManyToManyField(User)
class ModeratedModel(models.Model):
"""Class to implement a model that is moderated by a supervisor"""
is_approved = models.BooleanField(default=False)
def get_parent_instance(self):
"""
If the model already has a parent, override to return the parent's type
For example, for a BlogPost model it could return self.parent_blog
"""
# Get self's ContentType then return ModeratedModelParent for that type
self_content_type = ContentType.objects.get_for_model(self)
try:
return ModeratedModelParent.objects.get(content_type=self_content_type)
except:
# Create it if it doesn't already exist...
return ModeratedModelParent.objects.create(content_type=self_content_type).save()
class Meta:
abstract = True
Vì vậy, bây giờ chúng ta nên có một, tái sử dụng được chút generic mã mà chúng ta có thể xác định được phép cho một mô hình nhất định (mà chúng tôi sẽ xác định mô hình theo đó là Loại nội dung).
Tiếp theo, chúng ta có thể thực hiện chính sách của chúng tôi trong quản trị, một lần nữa thông qua một mô hình chung:
moderated.admin.py
class ModeratedModelAdmin(admin.ModelAdmin):
# Save our request object for later
def __call__(self, request, url):
self.request = request
return super(ModeratedModelAdmin, self).__call__(request, url)
# Adjust our 'is_approved' widget based on the parent permissions
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name == 'is_approved':
if not self.request.user in self.get_parent_instance().can_approve.all():
kwargs['widget'] = forms.CheckboxInput(attrs={ 'disabled':'disabled' })
# Enforce our "unapproved" policy on saves
def save_model(self, *args, **kwargs):
if not self.request.user in self.get_parent_instance().can_approve.all():
self.is_approved = False
return super(ModeratedModelAdmin, self).save_model(*args, **kwargs)
Khi đây là những thiết lập và làm việc, chúng ta có thể tái sử dụng chúng trên nhiều mô hình như tôi đã tìm thấy một khi bạn thêm quyền cấu trúc cho một cái gì đó như thế này, bạn dễ dàng muốn nó cho nhiều thứ khác.
Nói ví dụ bạn có một mô hình tin tức, bạn chỉ cần làm cho nó kế thừa từ mô hình mà chúng tôi vừa tạo và bạn tốt.
# in your app's models.py
class NewsItem(ModeratedModel):
title = models.CharField(max_length=200)
text = models.TextField()
# in your app's admin.py
class NewsItemAdmin(ModeratedModelAdmin):
pass
admin.site.register(NewsItem, NewsItemAdmin)
Tôi chắc chắn điều này có thể cung cấp cho bạn một số ý tưởng đóng vai trò là bệ phóng cho bất kỳ điều gì bạn quyết định triển khai.
Điều cuối cùng bạn phải làm, mà tôi sẽ để lại cho bạn, là triển khai lọc cho các mục is_approved
. (. Tức là bạn không muốn các mặt hàng không được chấp thuận niêm yết trên phần tin tức, phải không?)
bạn có thể có nghĩa là self.exclude = [ 'đã được phê duyệt'] trong get_form() và cũng có chút trục trặc trong changelist_view() ;) Cảm ơn, điều này có vẻ tuyệt vời và kết hợp với bit từ T. Câu trả lời của Stone, đó là chính xác những gì tôi đã tìm kiếm :) – minder
nếu tôi có 'đối tượng không có thuộc tính 'COOKIES'' thì sao? – andi
các quyền có được đăng ký ở mọi nơi khác để hiển thị trong mô-đun quản trị không? – andi