没有ForeignKey的Django中的Span模型

时间:2015-08-25 22:19:52

标签: python django django-models django-filter

我使用的是Python 2.7 / Django 1.8,并且有点像菜鸟。我坚持用这两个模型创建一个过滤器:

class A(models.Model):
     name = models.TextField()
     item_id = models.IntegerField()

class B(models.Model):
     entry_id = models.AutoField(primary_key=True)
     active = models.BooleanField()
     id = models.IntegerField()
     value = models.IntegerField()

此处的内容是A引用B id,但可能有多个条目具有相同的ID,除了一个条目之外的所有条目都有active = False。< / p>

我想要做的是,基本上:

 SELECT a.Name, b.value 
 FROM A a 
 JOIN B b ON a.id = b.item_id and a.active = true
 WHERE a.id = {some value}

我能弄清楚的唯一方法是:

 a_models = A.objects.filter(id=some_value)
 a_ids = [model.item_id for model in a_models]
 return B.objects.filter(active=True, id__in=a_ids)

这具有两次击中数据库的缺点,并且效率非常低。有没有办法做到这一点?模型的设计应该不同吗?

根据rofls的建议,这些是真实的型号名称和预期用途:

class Authorization(models.Model):
    active = models.BooleanField()
    user_root = models.IntegerField()
    name = models.TextField(max_length=64)

class Value(models.Model):
    entry_id = models.AutoField(primary_key=True)
    active = models.BooleanField()
    id = models.IntegerField()
    parent = models.IntegerField()
    name = models.TextField(max_length=64)
    value = models.TextField(max_length=2048)

目的是使Values表以分层方式存储值。使用父级维护层次结构 - &gt; ID。所以,例如:

 name                value
 /                   ''
 +-> folder1         ''
   +-> value         'some value'

在Values表中看起来像这样:

 entry_id | active | id | parent | name    | value
        0 |   True |  1 |      1 |       / | 
        1 |   True |  2 |      1 | folder1 | 
        2 |   True |  3 |      2 |  value1 | some value

请注意,id与entry_id不同,并且它允许使用历史记录。例如,更改id=3的值是entry_id=2的有效False,并使用active=True, id=3, parent=2输入新值。 DB设计明智,它是非常基本的东西。

它让Django变得复杂(特别是像我这样的人刚刚开始试图绕过ORM),因为用户角色是一种价值,我认为它们属于应用程序的一部分存储价值。因此,Authorization.user_root指向一个id,它是所有相关设置的父级。

对不起文字墙。这是我试图解决的实际问题:给定用户授权名称,我如何知道哪些用户拥有它?如果这是SQL,查询将如下所示:

 SELECT a.name, v.value
 FROM Authorization a 
 JOIN Value v ON a.user_root = v.parent and v.active = 1
 WHERE v.name = `{some name}` and v.active = 1

2 个答案:

答案 0 :(得分:1)

好的,不确定这是否是Django这样做的方式,但这就是我最终做的事情:

def get_values(self, env):
    class ValUsers(models.Model):
        name = models.TextField(max_length=64)
        value = models.TextField(max_length=2048)
    ret = EnvUsers.objects.raw(
        'SELECT a.id, a.name, v.value '
        ' FROM Authorization a, Value v ' 
        ' WHERE a.user_root = v.parent '
        '      and a.active = %s '
        '      and v.active = %s '
        '      and v.name = %s ',
        [True, True, env]
    )

    return {u.name: u.value for u in ret}

答案 1 :(得分:0)

您的模型不是由FK链接的,但您可以跳过这一步:

A.objects.vales_list('item_id', flat=True).filter(id=some_value)
return B.objects.filter(active=True, id__in=a_ids)