首页 文章

使用组名注释django用户查询集

提问于
浏览
2

鉴于我有一个django模型,它有一个与自身链接的ForeignKey .

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 == Truesuccessor 字段为对象的NULL时 .

现在我想做类似的事情,但不知道从哪里开始!

捆绑的 django.contrib.auth.models.Userdjango.contrib.auth.models.Group 模型具有ManyToMany关系

对于我的项目,有多种用户组类型,例如客户/营销/财务等

我想要做的是...使用 is_FOO 字段注释一个 User 查询集,其中 FOO 是一个组名 . 例如 is_customeris_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 数据库功能!

这有可能吗?让我入门的任何提示或技巧?

任何帮助将得到真诚的赞赏 . 非常感谢

1 回答

  • 1

    I have 2 solutions for the problem :-)

    鉴于我正在使用django auth用户模型

    from django.contrib.auth.models import User
    

    和我感兴趣的群组名称:

    CUSTOMER_GROUP_NAME = 'customer'
    

    Solution 1 - 正如Todor Velichkov在django-users谷歌小组中所建议的那样 .

    他的答案略有修改版本如下:

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

    链接到原始答案:https://groups.google.com/d/msg/django-users/BLCGZtUzEcY/w5w87frbBgAJ


    我做了一些研究,并了解了django条件表达式 .

    文件:https://docs.djangoproject.com/en/1.9/ref/models/conditional-expressions/

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

    我认为“解决方案2”更清晰,更易于阅读 . 所以我会用它:-)

相关问题