Как добавить собственное разрешение к модели User в django?

в django по умолчанию, когда syncdb запускается с установленным django.contrib.auth, он создает разрешения по умолчанию для каждой модели ... например, foo.can_change, foo.can_delete и foo.can_add. Чтобы добавить пользовательские разрешения к моделям, можно добавить класс Meta: в модель и определить разрешения там, как описано здесь https://docs.djangoproject.com/en/dev/topics/auth/#custom-permissions

Мой вопрос в том, что мне делать, если я хочу добавить настраиваемое разрешение для модели User? как foo.can_view. Я мог бы сделать это с помощью следующего фрагмента,

ct = ContentType.objects.get(app_label='auth', model='user')
perm = Permission.objects.create(codename='can_view', name='Can View Users', 
                                  content_type=ct)
perm.save()

Но мне нужно что-то, что хорошо работает с syncdb, например класс Meta в моих пользовательских моделях. Должен ли я просто иметь их в классе Meta: в UserProfile, поскольку это способ расширить модель пользователя. но это ПРАВИЛЬНЫЙ способ сделать это? Разве это не привязало бы его к модели UserProfile?


person gsin    schedule 11.10.2011    source источник
comment
Вы можете сделать это при миграции модели: stackoverflow.com/a/32706020/538284   -  person Omid Raha    schedule 22.09.2015


Ответы (4)


Вы можете сделать что-то вроде этого:

в __init__.py вашего приложения Django добавьте:

from django.db.models.signals import post_syncdb
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import models as auth_models
from django.contrib.auth.models import Permission

# custom user related permissions
def add_user_permissions(sender, **kwargs):
    ct = ContentType.objects.get(app_label='auth', model='user')
    perm, created = Permission.objects.get_or_create(codename='can_view', name='Can View Users', content_type=ct)
post_syncdb.connect(add_user_permissions, sender=auth_models)
person Dzejkob    schedule 13.11.2012
comment
Вставить __init__.py и подключиться к post_syncdb, вероятно, будет хорошей идеей, но приведенный выше код не сработал для меня. Я должен использовать ContentType.objects.get_for_model(model=auth_models.User). В противном случае это сработало. - person brianmearns; 13.12.2013
comment
post_syncdb больше не похоже на сигнал - person Yokhen; 13.03.2020

Я не думаю, что здесь есть "правильный" ответ, но я использовал тот же код, что и вы, за исключением того, что я изменил Permission.objects.create на Permission.objects.get_or_create, и это сработало, чтобы синхронизировать с syncdb

person leech    schedule 09.03.2012
comment
не будет get_or_create, создать другое разрешение, если имя изменится, но кодовое имя останется прежним? - person Amogh Talpallikar; 05.11.2014
comment
вы должны использовать кодовое имя только как часть get или create и указать имя по умолчанию - person leech; 05.11.2014

Обновленный ответ для Django 1.8. Сигнал pre_migrate используется вместо pre_syncdb, поскольку syncdb устарел, и в документации рекомендуется использовать pre_migrate вместо post_migrate, если сигнал изменит базу данных. Также @receiver используется для подключения add_user_permissions к сигналу.

from django.db.models.signals import pre_migrate
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import models as auth_models
from django.contrib.auth.models import Permission
from django.conf import settings
from django.dispatch import receiver


# custom user related permissions
@receiver(pre_migrate, sender=auth_models)
def add_user_permissions(sender, **kwargs):
    content_type = ContentType.objects.get_for_model(settings.AUTH_USER_MODEL)
    Permission.objects.get_or_create(codename='view_user', name='View user', content_type=content_type)
person mcastle    schedule 01.08.2015
comment
Могу я спросить, в какой файл мне нужно поместить этот код? Я думал, что это должно было быть установлено в моделях, как в более ранней версии Django, но я не уверен ... - person softwareplay; 03.03.2016
comment
@mcastle Я поместил это в __init__.py, но соответствующий запрос DoesNotExist: ContentType не существует. ошибка все еще приближается - person Gobi Dasu; 03.01.2017
comment
Я не уверен, что ваш аргумент sender верен, это должен быть экземпляр приложения, например `` из django.apps import apps sender = apps.get_app_config ('auth') `` - person Andre Miras; 14.05.2019

Это немного взломано, но все равно упомяну об этом здесь для справки.

У моего сайта есть общая модель под названием Setting, в которой хранятся различные настройки, касающиеся сайта, которые я хочу, чтобы определенные пользователи могли редактировать, без необходимости обращаться ко мне через разработчика (например, ограничение на регистрацию, адрес, стоимость элементов и т. Д. ).

Все разрешения, которые плохо отображаются на других моделях (например, «Отправить электронное письмо с напоминанием пароля студенту», «Создать отчет о согласовании платежей», «Создать квитанцию ​​в формате PDF»), которые на самом деле относятся только к страницам, которые просматриваются в области администрирования. , попади на эту Setting модель.

Например, вот модель:

class Setting(models.Model):
    name = models.CharField(max_length=50, unique=True)
    slug = models.SlugField(editable=False)
    description = models.TextField()
    value = models.TextField()
    class Meta:
        #for permissions that don't really relate to a particular model, and I don't want to programmatically create them.
        permissions = (
            ("password_reminder", "Send Password Reminder"),
            ("generate_payment_reconciliation_report", "Generate Payment Reconciliation Report"),
            ("generate_pdf_receipt", "Generate PDF Receipt"),
        )

Относятся ли каждая из этих настроек строго к модели Setting? Нет, поэтому я сказал, что это немного взломано. Но приятно, что теперь я могу просто сбросить все эти разрешения здесь, а команды миграции Django позаботятся обо всем остальном.

person thespacecamel    schedule 14.06.2019