0

在英语中,我想检查用户的类型是查看者、版主还是管理员。

这是我的相关部分models.py

class UserType( models.Model ) :
    name = models.CharField( max_length = 135 )

    # id |       name
    #----+------------------
    #  1 | tenant
    #  2 | property manager
    #  3 | property owner
    #  4 | vendor manager
    #  5 | vendor
    #  6 | viewer
    #  7 | moderator
    #  8 | administrator

class UserProfile( models.Model ) :
    user       = models.OneToOneField( User )
    user_types = models.ManyToManyField( UserType, null = True, blank = True )

顺便说一句,我设置user.profile为与user.get_profile().

在我的views.py代码中,我想做检查。我发现

[ user_type.pk for user_type in user.profile.user_types.all() ]

会给我一个pk's for the user's的列表user_type,就像这样[ 1, 2, 6 ]。这意味着该特定用户是租户 (1)、物业经理 (2) 和查看者 (6)。

如果我只想检查一个user_type,那么我可以简单地做

if 6 in [ user_type.pk for user_type in user.profile.user_types.all() ] :
    # This user is a viewer

但是如何检查多个 user_types/pks?我想做类似的事情

# This won't work
if [ 6, 7, 8 ] in [ user_type.pk for user_type in user.profile.user_types.all() ] :
    # This user is either a viewer, moderator, or administrator

我的列表理解方法也是检查user_typesDjango方式吗?看起来不像,但我不知道如何在 Django 中干净地查询它。

欢迎任何提示和建议。提前致谢!

编辑:

我刚刚发现我可以用更多的 Django 方式列出 pksvalues_list

user_types = user.profile.user_types.values_list( 'pk', flat = True )
# [ 1, 2, 6 ]

我还发现我可以像这样检查多个值

if len( set( [ 1, 9 ] ).intersection( set( user_types ) ) )
    # True because of 1 is in user_types (don't care about 9)

if len( set( [ 4, 99 ] ).intersection( set( user_types ) ) )
    # False because 4 nor 99 is in user_types

但即使这种set方法似乎也不是对 Django 非常友好。一定有更简单的方法吧?

4

1 回答 1

2

只需这样做:

def has_roles(user, roles):
    return user.profile.user_types.filter(pk__in=roles).count() == len(roles)

print has_roles(user, [6,7,8])

PS 我会回避使用硬编码的 PK ID 号码作为您的标识符。太多的事情可能会出错。而是在运行时定义映射并按名称引用它们。多方面会有所改善:

  • 您的代码将更容易阅读
  • Django将第一个项目卸载模型实例匹配到数据库
  • 从那时起,您可以缓存 ID 而无需再次询问数据库

然后你可以这样做:

class UserType( models.Model ):
    TYPES = (( 'tenant', 'Tenant'),
             ( 'propman', 'Property Manager'),
             ( 'propown', 'Property Owner'),
             ( 'vendman', 'Vendor Manager'),
             ( 'vendor', 'Vendor'),
             ( 'viewer', 'Viewer'),
             ( 'moderator', 'Moderator'),
             ( 'admin', 'Administrator'))

    name = models.CharField( max_length = 135, choices=TYPES )

def has_role(user, role):
    return user.profile.user_types.filter(name=role).count() == 1

def has_roles(user, roles):
    return user.profile.user_types.filter(name__in=roles).count() == len(roles)

print has_roles(user, ['viewer','moderator','admin'])

最后,您可以将上面的两个函数添加到:

class UserProfile( models.Model ) :
    user       = models.OneToOneField( User )
    user_types = models.ManyToManyField( UserType, null = True, blank = True )


    def has_role(self, role):
        return self.user_types.filter(name=role).count() == 1

    def has_roles(self, roles):
        return self.user_types.filter(name__in=roles).count() == len(roles)

然后在将来像这样使用它:

u = User.objects.get(username='me')
if u.userprofile.has_role('admin'):
    print 'I have the powah!'
于 2012-04-09T00:24:57.457 回答