用组名注释 django 用户查询集
Annotate django user queryset with group names
鉴于我有一个 Django 模型,它有一个链接到自身的外键。
class DjangoModel():
[...]
successor = models.ForeignKey('self', null=True)
我能够像这样编写一个自定义的 Django 数据库函数:
from django.db.models import BooleanField
from django.db.models import Func
class IsNull(Func):
"""
See docs: https://docs.djangoproject.com/en/1.8/ref/models/database-functions/
"""
template = '%(expressions)s IS NULL'
def __init__(self, *args, **kwargs):
kwargs['output_field'] = BooleanField()
super(IsNull, self).__init__(*args, **kwargs)
所以我可以这样做:
queryset = DjangoModel.objects.all()
queryset = queryset.annotate(**{'is_latest': IsNull('successor')})
如果使用 queryset.values()
.. 我得到
[{'pk': 1, is_latest': True}, {'pk': 2, 'is_latest': False}, ]
其中 is_latest == True
当 successor
字段对于对象为 NULL 时。
现在我想做类似的事情,但不知道从哪里开始!
捆绑的 django.contrib.auth.models.User
与 django.contrib.auth.models.Group
模型
具有多对多关系
对于我的项目,有多个用户组类型,例如客户/营销/财务等
我想做的是用 is_FOO
字段注释 User
查询集,其中 FOO
是组名。例如 is_customer
或 is_marketing
所以如果我在查询集上使用 .values()
,我应该得到这样的结果:
[{'pk': 1, 'is_customer': True, 'is_marketing': False }, {'pk': 1, 'is_customer': True, 'is_marketing': True }]
组名可以硬编码,例如
queryset.annotate(**{'is_customer': IsGroupMember('customer')})
我只需要 IsGroupMember
数据库功能方面的帮助!
这可能吗?有什么提示或技巧可以帮助我入门吗?
我们将不胜感激任何帮助。非常感谢
我有 2 个解决方案:-)
考虑到我使用的是 django 身份验证用户模型
from django.contrib.auth.models import User
以及我感兴趣的群组名称:
CUSTOMER_GROUP_NAME = 'customer'
解决方案 1 — 正如 Todor Velichkov 在 django-users google 组中所建议的那样。
他的回答略有修改:
from django.db.models.expressions import RawSQL
def is_group_member(group_name):
return RawSQL("""EXISTS(
SELECT 1 FROM `auth_group`
WHERE `auth_group`.`name` = %s
AND `auth_group`.`id` IN (
SELECT `auth_user_groups`.`group_id`
FROM `auth_user_groups`
WHERE `auth_user_groups`.`user_id` = `auth_user`.`id`
)
)""", (group_name,), output_field=BooleanField())
qs1 = User.objects.all().annotate(is_customer=is_group_member(CUSTOMER_GROUP_NAME))
Link 原答案:https://groups.google.com/d/msg/django-users/BLCGZtUzEcY/w5w87frbBgAJ
我做了更多研究并了解了 django 条件表达式。
文档:https://docs.djangoproject.com/en/1.9/ref/models/conditional-expressions/
解决方案 2 — 使用 django 表达式:-)
from django.contrib.auth.models import User
from django.db.models import BooleanField
from django.db.models import When, Case, Value
query = When(groups__name__in=[CUSTOMER_GROUP_NAME, ], then=Value(1))
qs2 = User.objects.annotate(
is_customer=Case(query, default=Value(0), output_field=BooleanField()))
我认为 "Solution 2" 更清晰易读。所以我将使用它:-)
鉴于我有一个 Django 模型,它有一个链接到自身的外键。
class DjangoModel():
[...]
successor = models.ForeignKey('self', null=True)
我能够像这样编写一个自定义的 Django 数据库函数:
from django.db.models import BooleanField
from django.db.models import Func
class IsNull(Func):
"""
See docs: https://docs.djangoproject.com/en/1.8/ref/models/database-functions/
"""
template = '%(expressions)s IS NULL'
def __init__(self, *args, **kwargs):
kwargs['output_field'] = BooleanField()
super(IsNull, self).__init__(*args, **kwargs)
所以我可以这样做:
queryset = DjangoModel.objects.all()
queryset = queryset.annotate(**{'is_latest': IsNull('successor')})
如果使用 queryset.values()
.. 我得到
[{'pk': 1, is_latest': True}, {'pk': 2, 'is_latest': False}, ]
其中 is_latest == True
当 successor
字段对于对象为 NULL 时。
现在我想做类似的事情,但不知道从哪里开始!
捆绑的 django.contrib.auth.models.User
与 django.contrib.auth.models.Group
模型
对于我的项目,有多个用户组类型,例如客户/营销/财务等
我想做的是用 is_FOO
字段注释 User
查询集,其中 FOO
是组名。例如 is_customer
或 is_marketing
所以如果我在查询集上使用 .values()
,我应该得到这样的结果:
[{'pk': 1, 'is_customer': True, 'is_marketing': False }, {'pk': 1, 'is_customer': True, 'is_marketing': True }]
组名可以硬编码,例如
queryset.annotate(**{'is_customer': IsGroupMember('customer')})
我只需要 IsGroupMember
数据库功能方面的帮助!
这可能吗?有什么提示或技巧可以帮助我入门吗?
我们将不胜感激任何帮助。非常感谢
我有 2 个解决方案:-)
考虑到我使用的是 django 身份验证用户模型
from django.contrib.auth.models import User
以及我感兴趣的群组名称:
CUSTOMER_GROUP_NAME = 'customer'
解决方案 1 — 正如 Todor Velichkov 在 django-users google 组中所建议的那样。
他的回答略有修改:
from django.db.models.expressions import RawSQL
def is_group_member(group_name):
return RawSQL("""EXISTS(
SELECT 1 FROM `auth_group`
WHERE `auth_group`.`name` = %s
AND `auth_group`.`id` IN (
SELECT `auth_user_groups`.`group_id`
FROM `auth_user_groups`
WHERE `auth_user_groups`.`user_id` = `auth_user`.`id`
)
)""", (group_name,), output_field=BooleanField())
qs1 = User.objects.all().annotate(is_customer=is_group_member(CUSTOMER_GROUP_NAME))
Link 原答案:https://groups.google.com/d/msg/django-users/BLCGZtUzEcY/w5w87frbBgAJ
我做了更多研究并了解了 django 条件表达式。
文档:https://docs.djangoproject.com/en/1.9/ref/models/conditional-expressions/
解决方案 2 — 使用 django 表达式:-)
from django.contrib.auth.models import User
from django.db.models import BooleanField
from django.db.models import When, Case, Value
query = When(groups__name__in=[CUSTOMER_GROUP_NAME, ], then=Value(1))
qs2 = User.objects.annotate(
is_customer=Case(query, default=Value(0), output_field=BooleanField()))
我认为 "Solution 2" 更清晰易读。所以我将使用它:-)