0

I'm using django-guardian and have 3 table that did not connected directly with foreign keys. Guardian_groupobjectpermission table can connected with any table by object_pk <-> table.pk Also Guardian_groupobjectpermission connected with auth_persmission by permission_id -> auth_permission.pk. Auth_persmission has codename field. Please look at table scheme image:

table scheme

I need to get data from pybb_forum table that have codename = 'can_view'.

In sql this query will looks like:

mysql> select * from pybb_forum as ff join guardian_groupobjectpermission as gg on ff.id = gg.object_pk join auth_permission as pp on gg.permission_id = pp.id where codename = 'view_forum';

But i don't know have to create this query using django ORM. Is it possible ?

Something like

Forum.objects.filter(groupobjectpermission__permission__codename='view_forum')

?

Here is model code:

# django auth permission model:
class Permission(models.Model):
    name = models.CharField(_('name'), max_length=50)
    content_type = models.ForeignKey(ContentType)
    codename = models.CharField(_('codename'), max_length=100)

# guardian group permission model
class GroupObjectPermissionBase(BaseObjectPermission):
    permission = models.ForeignKey(Permission)
    content_type = models.ForeignKey(ContentType)
    object_pk = models.CharField(_('object ID'), max_length=255)
    content_object = GenericForeignKey(fk_field='object_pk')
    group = models.ForeignKey(Group) # reference to django group

class Forum(models.Model):
    name = models.CharField(_('Name'), max_length=80, default='')
    slug = models.SlugField(default='', unique=True)
    hidden = models.BooleanField(_('Hidden'), blank=False, null=False, default=False)
    headline = models.TextField(_('Headline'), blank=True, null=True)

    class Meta(object):
        permissions = (
           ('view_forum', 'Only view forum'),
    )
4

2 回答 2

0

好吧,就我而言,我可以在不使用 JOINS 的情况下重写 SQL 查询,将其替换为 WHERE:

 SELECT * FROM pybb_forum as ff,guardian_groupobjectpermission as gg, 
           auth_permission as pp  
     WHERE codename = 'view_forum'      
     AND gg.group_id in (1,2,3)     
     AND gg.content_type_id = 9 
     AND  ff.id = gg.object_pk 
     AND gg.permission_id = pp.id;

现在我们可以使用 extra 轻松创建 ORM 查询:

 Forum.objects.extra(
    tables = ['guardian_groupobjectpermission', 'auth_permission'],
    where = [
      """ codename = "view_forum"
      AND guardian_groupobjectpermission.group_id in (1,2,3)
      AND guardian_groupobjectpermission.content_type_id = 9
      AND pybb_forum.id = guardian_groupobjectpermission.object_pk
      AND guardian_groupobjectpermission.permission_id = auth_permission.id"""
    ])

但是这样的查询对于其他开发人员来说并不那么容易阅读:(

于 2013-08-15T20:34:14.213 回答
0

我找到了另一种解决方案,django 可以处理泛型关​​系字段之间的连接。 http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#reverse-generic-relations

所以我们需要在 Forum 模型中再添加一个属性:

  permissions =  generic.GenericRelation(GroupObjectPermission, object_id_field='object_pk') 

或者做猴子补丁:

 Forum.add_to_class('permissions', generic.GenericRelation(GroupObjectPermission, object_id_field='object_pk'))

 Forum.objects.all()[0].permissions.all() 

将返回当前论坛的所有权限

于 2013-08-16T22:57:57.800 回答