Pull to refresh

Ограничиваем интерфейс редактирования с помощью прокси-моделей

Reading time2 min
Views9K
Административный интерфейс джанго позволяет настраивать права доступа к объектам различных приложений. Для любой модели любого приложения вы можете разрешить пользователю три действия: добавлять новые объекты, редактировать и удалять существующие объекты.

А что делать, если мы хотим разрешить пользователю редактировать только часть полей? И в то же время оставить возможность другим пользователям редактировать все поля.

Нам помогут прокси модели. В терминологии джанго прокси-модель — это объект, обладающий интерфейсом обычной модели, но не привязанный к базе данных, вернее он привязан к данным другой модели. Для чего это нужно?

В документации джанго используется следующий пример. Мы хотим, чтобы объекты модели auth.User обладали дополнительным методом. Для этого мы создаём прокси-модель на базе модели auth.User, описываем там этот метод и используем, где нужно, эту прокси-модель вместо оригинальной.

Вернёмся к нашей задаче. Прокси-модели полезны тем, что мы можем запретить пользователю работать с оригинальной моделью, разрешить ему доступ к прокси-модели и настроить форму редактирования так, чтобы были доступны только разрешённые поля.

Давайте, представим, что у нас есть следующая модель:

class Article(models.Model):
    title = models.CharField(...)
    body = models.CharField(...)
    tags = models.CharField(...)


Мы хотим, чтобы редактор мог заходить в админку, видеть список статей, мог менять тэги, но не мог менять заголовок или тело статьи.

Давайте создадим для начала прокси-модель:

class ArticleEditProxy(Article):
    class Meta:
        proxy = True


Теперь зарегистрируем эту модель в admin.site и назначим ей специальную форму, в которой доступны для редактирования только тэги

class ArticleEditProxyForm(forms.ModelForm):
    class Meta:
        model = ArticleEditProxy
        fields = ['tags']


class ArticleEditProxyAdmin(admin.ModelAdmin):
    list_display = ['title', 'tags']
    form = ArticleEditProxyForm
    readonly_fields = ['title', 'body']

admin.site.register(ArticleEditProxy, ArticleEditProxyAdmin)


Теперь, при заходите в админку пользователь сможет видеть список статей и сможет менять тэги у любой статьи, он также будет видеть заголовок и содержимое статьи, но не сможет их поменять.

Ещё один нюанс. Права доступа к объектам различных моделей реализованы в джанге через объекты модели Permission. Чтение — это один объект Permission, запись — другой, ещё один — удаление. Permission объекты для новых моделей создаются во время запуска команды manage.py syncdb. Если на момент создания прокси-модели ваше приложение контролировалось через south, то объекты Permission не будут созданы, south «не заметит» вашу прокси-модель, а операция syncdb не работает с приложениями, обслуживаемыми south.

Вам придётся создать миграцию, которая будет посылать сигнал post_syncdb для вашей прокси-модели.

class Migration(SchemaMigration):
    def forwards(self, orm):
        db.send_create_signal('myapp', ['ArticleEditProxy'])


Подробности хака с миграцией я узнал в этом блоге.
Tags:
Hubs:
Total votes 31: ↑27 and ↓4+23
Comments13

Articles