Есть модель статей. Нужно два разных интерфейса редактирования в админке для модератора и авторов статей. Авторы могут видеть и редактировать только свои статьи. Модератор видит все статьи и может радктировать флаг отображения статьи на сайте, который, при добавлении статей авторами, равен False по умолчанию. Также убираем стандартную возможность удаления, что бы никто не мог удалять статьи кроме модератора.
Пример решения есть на
http://getopts.blogspot.com/2008/12/django.html, там это сделано
через переопределение методов has_change_permission
и других, но
всё это как-то не наглядно.
Тем более, вдруг кому-то понадобится много разных интерфейсов для одной модели ))
Недавно в Django добавили унаследованые
proxy-модели. Proxy-модель использует ту же таблицу в базе
данных, что и родительская, а Django для неё создаёт отдельный
content_type
, то есть для определения прав доступа в админке
можно просто создать группу авторов с правами редактирования
Proxy-модели, и груgпу модераторов, которые будут редактировать
основную таблицу.
Файл models.py
class DjemPost(models.Model):
name = models.CharField('Название', max_length=255)
slug = models.SlugField(unique=True)
annotation = models.TextField('Аннотация')
body = models.TextField('Содержние')
active = models.BooleanField('Активная?', default=False, \
help_text='Неактивная статья не будет отображатся. Не изменяется \
автором статьи (для модерации).')
hide = models.BooleanField('Скрытая?', default=False, \
help_text='''Скрытая статья не будет отображаться.
Может изменяться автором статьи.<br/>Может использоваться,
например, для временного скрытия недописаной статьи.''')
added = models.ForeignKey(User, editable=False)
created_at = models.DateTimeField('Добавлено', auto_now_add=True)
class Meta:
verbose_name = 'Статью'
verbose_name_plural = 'Статьи'
ordering = ['-created_at']
class ProxyPostManager(models.Manager):
'''
Менеджер для Proxy-модели. Не знаю почему, но без него в админке не показывается
ни одна статья, но количество отображается верно.
'''
def get_query_set(self):
return Post.objects.get_query_set()
class ProxyPost(Post):
'''
Proxy-модель. Можно добавить ещё всяких методов. Например, кастомного отображения
каких-либо полей в админке.
'''
objects = ProxyPostManager()
class Meta:
proxy = True
verbose_name = 'Вашу статью'
verbose_name_plural = 'Ваши статьи'
Файл admin.py
class BasePostAdmin(admin.ModelAdmin):
'''
Основной ModelAdmin для статьи, от которого будем унаследоваться и переопределять
необходимое, конкретно для каждого типа интерфейса.
'''
prepopulated_fields = {"slug": ("name", )}
list_select_related = True
actions = ['make_hiden']
save_on_top = True
class Media:
js = (
'js/tiny_mce/tiny_mce.js',
)
def save_model(self, request, obj, form, change):
if not change:
obj.added = request.user
obj.save()
def make_hiden(self, request, queryset):
queryset.update(hide=True)
make_hiden.short_description = "Скрыть"
def has_delete_permission(self, request, obj=None):
#Удалять может только суперпользователь
return request.user.is_superuser
def get_actions(self, request=None):
'''
Убираем стандартный функционал удаления для всех, кроме суперпользователя. Action
в Django добавили, а удаление стандартных - нет.
'''
actions = super(BaseDjemPostAdmin, self).get_actions(request)
if not request.user.is_superuser:
del(actions['delete_selected'])
return actions
class ProxyPostAdmin(BaseDjemPostAdmin):
'''
AdminModel для группы авторов. Убрали редактирование поля активности.
'''
exclude = ('active', )
list_display = ('name', 'annotation', 'hide', 'created_at')
list_filter = ('hide')
search_fields = ['name']
def has_change_permission(self, request, obj=None):
#убираем право редактироваие "чужих" статей
has_class_permission = super(ProxyDjemPostAdmin, self).has_change_permission(request, obj)
if not has_class_permission:
return False
if obj is not None and request.user.id != obj.added.id:
return False
return True
def queryset(self, request):
#Выводим только статьи автора
qs = super(ProxyDjemPostAdmin, self).queryset(request).filter(added=request.user)
return qs
class PostAdmin(BaseDjemPostAdmin):
#AdminModel для группы модераторов
list_display = ('name', 'added', 'active', 'hide', 'created_at')
list_filter = ('active', 'hide')
search_fields = ['name', 'added__username']
#Регистрируем модели
admin.site.register(Post, PostAdmin)
admin.site.register(ProxyPost, ProxyPostAdmin)