我正在使用django-guardian并且有3个表没有直接连接外键。 Guardian_groupobjectpermission表可以通过object_pk< - >连接任何表。 table.pk Guardian_groupobjectpermission也通过permission_id连接到auth_persmission - > auth_permission.pk。 Auth_persmission具有代号字段。请看表格方案图片:
我需要从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'),
)
答案 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()
将返回当前论坛的所有权限