gpt4 book ai didi

django - 如何在 Django 的自定义帐户模型中覆盖 user.groups 以实现 "virtual"组?

转载 作者:行者123 更新时间:2023-12-04 14:08:27 30 4
gpt4 key购买 nike

我在使用 PermissionsMixin 的 Django 应用程序中有一个自定义帐户类:

class Account(AbstractBaseUser, PermissionsMixin):

我们的 CMS 在此类上调用各种 .groups 方法以确定权限。

我们本质上想要覆盖从这个自定义 Account 类中的 .groups 返回的查询集,并在特定条件下注入(inject)一个额外的组。 (即用户有一个有效的订阅,然后我们希望将“成员”作为该用户的组之一返回,尽管他们实际上并不在组中。)

我们应该如何处理这种覆盖?我们需要获取原始组,以免破坏基本组功能,然后将我们的“虚拟”组注入(inject)查询集中。

最佳答案

覆盖 get_queryset方法ManyRelatedManager . ManyRelatedManager 的对象类可以访问父实例。

代码示例:

def add_custom_queryset_to_many_related_manager(many_related_manage_cls):
class ExtendedManyRelatedManager(many_related_manage_cls):
def get_queryset(self):
qs = super(ExtendedManyRelatedManager, self).get_queryset()
# some condition based on the instance
if self.instance.is_staff:
return qs.union(Group.objects.filter(name='Gold Subscription'))
return qs

return ExtendedManyRelatedManager

ManyRelatedManager class is obtained from the ManyToManyDescriptor.


class ExtendedManyToManyDescriptor(ManyToManyDescriptor):

@cached_property
def related_manager_cls(self):
model = self.rel.related_model if self.reverse else self.rel.model
return add_custom_queryset_to_many_related_manager(create_forward_many_to_many_manager(
model._default_manager.__class__,
self.rel,
reverse=self.reverse,
))

Associated the ExtendedManyToManyDescriptor with groups field when the Account class is initialized.


class ExtendedManyToManyField(ManyToManyField):

def contribute_to_class(self, cls, name, **kwargs):
super(ExtendedManyToManyField, self).contribute_to_class(cls, name, **kwargs)
setattr(cls, self.name, ExtendedManyToManyDescriptor(self.remote_field, reverse=False))

Override PermissionsMixin to use ExtendedManyToManyField for groups field instead of ManyToManyField.


class ExtendedPermissionsMixin(PermissionsMixin):
groups = ExtendedManyToManyField(
Group,
verbose_name=_('groups'),
blank=True,
help_text=_(
'The groups this user belongs to. A user will get all permissions '
'granted to each of their groups.'
),
related_name="user_set",
related_query_name="user",
)

class Meta:
abstract = True

引用: django.db.models.fields.related_descriptors.create_forward_many_to_many_manager
测试:
account = Account.objects.get(id=1)
account.is_staff = True
account.save()

account.groups.all()

# output
[<Group: Gold Subscription>]

关于django - 如何在 Django 的自定义帐户模型中覆盖 user.groups 以实现 "virtual"组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54615494/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com