django ORM queryset没有直接连接

时间:2013-08-15 01:24:29

标签: django orm

我正在使用django-guardian并且有3个表没有直接连接外键。 Guardian_groupobjectpermission表可以通过object_pk< - >连接任何表。 table.pk Guardian_groupobjectpermission也通过permission_id连接到auth_persmission - > auth_permission.pk。 Auth_persmission具有代号字段。请看表格方案图片:

table scheme

我需要从pybb_forum表中获取具有codename ='can_view'的数据。

在sql中,此查询将如下所示:

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';

但我不知道是否必须使用django ORM创建此查询。 有可能吗?

这样的东西
Forum.objects.filter(groupobjectpermission__permission__codename='view_forum')

以下是型号代码:

# 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'),
    )

2 个答案:

答案 0 :(得分: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;

现在我们可以使用额外的东西轻松创建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"""
    ])

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

答案 1 :(得分:0)

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

因此我们需要在论坛模型中再添加一个属性:

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

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