如何向 django 中的用户模型添加自定义权限?

发布于 2024-12-09 05:17:17 字数 810 浏览 1 评论 0原文

默认情况下,在 django 中,当安装了 django.contrib.auth 的情况下运行syncdb时,它会在每个模型上创建默认权限...如 foo.can_change 、 foo.can_delete 和 foo.can_add 。要向模型添加自定义权限,可以在模型下添加类 Meta: 并在那里定义权限,如下所述 https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#custom-permissions

我的问题是,如果我应该怎么做想要向用户模型添加自定义权限?像 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。我是否应该将这些放在 UserProfile 下的 Meta: 类中,因为这是扩展用户模型的方法。但这是正确的方法吗?这不会将其与 UserProfile 模型联系起来吗?

in django by default when syncdb is run with django.contrib.auth installed, it creates default permissions on each model... like foo.can_change , foo.can_delete and foo.can_add. To add custom permissions to models one can add class Meta: under the model and define permissions there, as explained here https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#custom-permissions

My question is that what should I do if I want to add a custom permission to the User model? like foo.can_view. I could do this with the following snippet,

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()

But I want something that plays nicely with syncdb, for example the class Meta under my custom models. Should I just have these in class Meta: under UserProfile since that is the way to extend the user model. but is that the RIGHT way to do it? Wouldn't that tie it to UserProfile model?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

粉红×色少女 2024-12-16 05:17:17

您可以执行以下操作:

在 Django 应用程序的 __init__.py 中添加:

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)

You could do something like this:

in the __init__.py of your Django app add:

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)
三寸金莲 2024-12-16 05:17:17

我认为这里没有“正确”的答案,但我使用了与您完全相同的代码,只是将 Permission.objects.create 更改为 Permission.objects.get_or_create 并且找到了与syncdb同步的工作

I don't think there is a "right" answer here, but i used the exact same code as you except i changed Permission.objects.create to Permission.objects.get_or_create and that worked find to sync with syncdb

帝王念 2024-12-16 05:17:17

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)

An updated answer for Django 1.8. The signal pre_migrate is used instead of pre_syncdb, since syncdb is deprecated and the docs recommend using pre_migrate instead of post_migrate if the signal will alter the database. Also, @receiver is used to connect add_user_permissions to the signal.

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)
蓝眸 2024-12-16 05:17:17

这有点hacky,但无论如何在这里提到它以供参考。

我的网站有一个名为 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 模型严格相关吗?不,这就是为什么我说这有点hacky。但很高兴我现在可以将所有这些权限转储到这里,Django 的迁移命令将处理其余的事情。

This is a bit hacky but mentioning it here anyway for reference.

My site has a generic model called Setting, which stores various settings concerning the site I want certain users to be able to edit, without needing to go through me the developer (like registration limit, or an address, or the cost of items, etc).

All the permissions that don't nicely map onto other models (eg "Send Password Reminder Email to Student", "Generate Payment Reconciliation Report", "Generate PDF Receipt"), which really just relate to pages that get viewed in the admin area, get dumped onto this Setting model.

For example, here's the model:

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"),
        )

Do each of those settings strictly relate to the Setting model? No, which is why I said this is a bit hacky. But it is nice that I can now just dump all those permissions here, and Django's migration commands will take care of the rest.

还在原地等你 2024-12-16 05:17:17

正如 @leech 在其答案的评论中指出的那样,您无法传递名称直接传递给 get_or_create 的参数。您必须将名称作为 defaults 字典的一部分包含在内。否则你会得到重复的键错误。

更改 @Dzejkob 的 answer 中的 get_or_create 调用,使其如下所示:

perm, created = Permission.objects.get_or_create(
    content_type=ct,
    codename='can_view', 
    defaults={'name': 'Can View Users'},
)

As @leech pointed out in a comment on their answer, you can't pass the name parameter to get_or_create directly. You have to include name as part of the defaults dict. Otherwise you'll get duplicate key errors.

Change the get_or_create call from @Dzejkob's answer to make it look like this:

perm, created = Permission.objects.get_or_create(
    content_type=ct,
    codename='can_view', 
    defaults={'name': 'Can View Users'},
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文