繁体   English   中英

Django中没有ForeignKey的Span模型

[英]Span models in Django without a ForeignKey

我正在使用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通过id引用B ,但是可能会有多个具有相同id的条目,除了一个之外,其他所有条目都具有active = False

我想做的基本上是:

 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)

目的是使“值”表以分层方式存储值。 使用父-> id维护层次结构。 因此,例如:

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

在“值”表中将如下所示:

 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包扎的人)的原因是,由于User角色是一种价值,我认为它们属于应用程序中存储值的部分。 因此, 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

好的,不确定这是否是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}

您的模型没有通过FK链接,但是您可以跳过以下步骤:

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

模型应该设计不同吗?

是。 您应该在A表和B表中都有一个foregin键,如下所示:

class A(models.Model):
    name = models.TextField()
    item_id = models.ForeignKey(B,through='id')

然后,您应该可以执行以下操作:

A.objects.filter(b__active=True)

有关更多信息,请参见Django文档

例如,多对多关系应类似地工作:

class A(models.Model):
    name = models.TextField()
    item_id = models.ManyToManyField(B,to_field='id')

另外,还不清楚您要使用B哪个id作为ForeignKey ,因此您实际上可能想ForeignKey

class A(models.Model):
    name = models.TextField()
    item_id = models.ForeignKey(B,through='entry_id')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM