Добавление разрешений для объекта для администратора django

Задний план

Я разрабатываю приложение django для сайта аренды для отпуска. Он будет иметь двух типов пользователей, арендаторов и управляющих недвижимостью.

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

Я понимаю, что администратор django по умолчанию не поддерживает это. Мне интересно, насколько сложно было бы добавить эту функциональность, и, если это возможно, лучший способ справиться с этим.


Цель

В идеале я рисую, что он работает примерно так:

auth уже разрешает такие права:

 отдых |  аренда |  Можно добавить аренду
 отдых |  аренда |  Можно изменить аренду
 отдых |  аренда |  Можно удалить аренду

Я хотел бы изменить это на что-то вроде:

 отдых |  аренда |  Можно добавить аренду
 отдых |  аренда |  Можно изменить арендную плату
 отдых |  аренда |  Можно удалить любую аренду
 отдых |  аренда |  Можно добавить собственную аренду
 отдых |  аренда |  Можете изменить арендную плату
 отдых |  аренда |  Можно снять собственную аренду

Возможное решение

Каким образом структура решит, принадлежит ли аренда (или что-то еще) пользователю? Я думаю, что он проверяет vacation.Rental Класс ForeignKey чтобы auth.User имеет ли он ForeignKey для auth.User (возможно, имеет определенное имя, например «владелец»).

  • При создании нового vacation.Rental ForeignKey поля ForeignKey будет принудительно ForeignKey к идентификатору текущего пользователя. Поле ForeignKey не будет отображаться в форме.

  • При перечислении арендной платы будет отображаться только аренда с ForeignKey соответствующая текущему пользователю.

  • При изменении арендной платы будет отображаться только аренда с ForeignKey соответствующая текущему пользователю. Поле ForeignKey не будет отображаться в форме.

Конечно, это должно быть способно работать для любой модели, имеющей соответствующее поле ForeignKey , а не только для нашей vacation.Rental модели.

До сих пор это звучит, или я должен идти в другом направлении?


осложнения

Теперь вот сложная часть; Я не уверен, как справиться с этим. Скажем, в прокате может быть много «RentalPhotos». RentalPhoto имеет ForeignKey к Rental . Пользователи должны иметь возможность добавлять фотографии в собственную аренду. Однако на фотографиях нет пользователя ForeignKey , поэтому нет возможности напрямую узнать, кому принадлежит фотография.

Может ли это быть разрешено каким-то обманом в рамках, следуя за ForeignKey s, пока объект не будет найден с пользователем ForeignKey ? Или я должен взять легкий путь и дать RentalPhoto (и все остальное «принадлежать» Rental ) собственный ForeignKey к соответствующему auth.User ? Второй подход потребует ненужного избыточности, первый, вероятно, потребует ненужных накладных расходов …

Если я пойду совершенно в заблуждение, пожалуйста, не стесняйтесь указывать мне в правильном направлении. Заранее благодарю за любую помощь.

4 Solutions collect form web for “Добавление разрешений для объекта для администратора django”

Я бы просто добавил метод к каждой модели is_owned_by(user) , и это зависит от модели, чтобы решить, принадлежит ли она этому пользователю или нет. В большинстве случаев is_owned_by может быть общей функцией в базовом классе модели, и вы можете настроить его в особых случаях. например

 class RentalPhoto(BaseModel): def is_owned_by(self, user): return self.rental.is_owned_by(user) 

Это достаточно общий и явный, вы будете иметь полный контроль над тем, как они себя ведут.

Чтобы добавить новое разрешение, вы можете добавить это к своим моделям, например

 class Rental(models.Model): # ... class Meta: permissions = ( ("can_edit_any", "Can edit any rentals"), ) 

Я думаю, вместо того, чтобы добавлять два разрешения для any и own , вы должны добавить только own разрешение, поэтому у каждого объекта уже есть can_edit который вы можете рассматривать, поскольку пользователь может редактировать только свой объект, и если у пользователя есть разрешение can_edit_any, то только ему разрешено редактировать все

Используя это, мы можем расширить auth, добавив пользовательский сервер, например

 class PerObjectBackend(ModelBackend): def has_perm(self, user_obj, perm, obj=None): allowed = ModelBackend.has_perm(self, user_obj, perm) if perm.find('any') >=0 : return allowed if perm.find('edit') >=0 or perm.find('delete') >=0: if obj is None: raise Exception("Perm '%s' needs an object"%perm) if not obj.is_owned_by(user_obj): return False return allowed 

Это очень быстрая реализация, на самом деле вы можете расширить объекты разрешений, чтобы проверить, нужны ли они и какие объекты или нет, например, permission.is_per_object а не выполнять грубый поиск строк, но это также должно работать, если у вас есть стандартные имена

Может ли это быть разрешено каким-то обманом в рамках, следуя за ForeignKeys, пока объект не будет найден с пользователем ForeignKey?

Я не вижу, где есть обманщик: RentalPhoto -> Аренда -> Пользователь. Чтобы получить пользователя для конкретного RentalPhoto, вы вызываете что-то вроде этого в примере:

 photo.rental.user 

После нескольких отношений за один шаг можно считать неинтеллектуальным.

Если вы не хотите реализовывать свой собственный сервер разрешения, я рекомендую вам использовать https://github.com/chrisglass/django-rulez. Вы сделаете то, что хотите, намного проще.

Это в документах Django .

В основном вы создаете собственный класс администратора для своей модели и определяете метод get_queryset . В вашем случае это может быть что-то вроде ниже. Суперпользователь увидит все арендные платы, а владелец – только его.

 class RentalAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super(RentalAdmin, self).get_queryset(request) if request.user.is_superuser: return qs return qs.filter(owner=request.user) 

Вот еще одно возможное руководство: https://code.djangoproject.com/wiki/RowLevelPermissions

  • Как я должен представлять бит int int в django admin?
  • Как скрыть метку поля для виджета HiddenInput в Django Admin?
  • Программно добавлять шаблоны URL в Django?
  • Как установить другой заголовок Inline в Django Admin?
  • Редактор Django Markdown не отображается
  • django admin встроил многие из многих настраиваемых полей
  • Как включить {{fieldset.fields}} в шаблоне Django в строку?
  • Как настроить страницу администратора auth.User Admin в Django CRUD?
  • Python - лучший язык программирования в мире.