У меня есть система вроде этого в проекте, который я только что закончил. Там будет много работы, чтобы поставить это вместе, но вот некоторые из компонентов, которые я должен был сделать мою работу системы:
Вам нужен способ, чтобы определить редактор и супервизора. Три способа сделать это: 1.) путем определения поля M2M, определяющего Supervisor [и предполагая, что все остальные, имеющие разрешение на чтение/запись, являются Редактором], 2.) создают 2 новые модели пользователей, которые наследуют пользователя [ вероятно, больше работы, чем необходимо] или 3.) используйте способность django.auth иметь класс UserProfile. Метод №1, вероятно, является наиболее разумным.
Как только вы можете определить, какой тип пользователя, вам нужен способ в целом обеспечить соблюдение авторизации, которую вы ищете. Я думаю, что лучший маршрут здесь, вероятно, является общей моделью администратора.
Наконец, вам понадобится модель типа «родитель», которая будет хранить разрешения для всех, что должно быть модерировано. Например, если у вас была модель Blog и модель BlogPost (при условии, что несколько блогов находятся на одном сайте), тогда Blog является родительской моделью (она может содержать разрешения того, кто ее одобряет). Однако, если у вас есть один блог и нет родительской модели для BlogPost, нам нужно место для хранения разрешений. Я нашел, что ContentType
хорошо работает здесь.
Вот некоторые идеи в коде (непроверенные и более концептуальные, чем фактические).
Сделайте новое приложение под названием «модерированное», которое будет содержать наш общий материал.
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
Так что теперь мы должны иметь общий, многоразовое бит кода, который мы можем определить разрешение для данной модели (которую мы будем идентифицировать модель по типу содержимого).
Далее, мы можем реализовать нашу политику в админке, опять-таки через общую модель:
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)
После их установки и работы, мы можем повторно используйте их во многих моделях, как я нашел, когда вы добавляете структурированные разрешения для чего-то вроде этого, вы легко хотите его для многих других вещей.
Скажите, например, что у вас есть модель новостей, вам просто нужно было бы унаследовать от модели, которую мы только что создали, и вы хороши.
# 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)
Я уверен, что я сделал некоторые ошибки кода и ошибки там, но мы надеемся, что это может дать вам некоторые идеи, чтобы действовать в качестве стартовой площадки для все, что вы решили реализовать.
Последнее, что вам нужно сделать, что я оставлю вам, - это реализовать фильтрацию для элементов is_approved
. (Т. Е вы не хотите, одобренные ООН пункты будут перечислены в разделе новостей, верно?)
вы, вероятно, имел в виду self.exclude = [ 'утвержден'] в get_form() и есть также небольшой глюк в changelist_view() ;) Спасибо, это выглядит великолепно и в сочетании с битами от T. Ответ Стоуна, это именно то, что я искал :) – minder
Что делать, если я получил 'объект не имеет атрибута 'COOKIES''? – andi
должны ли разрешения регистрироваться где-нибудь еще, чтобы их можно было видеть в модуле администратора? – andi