Python Django中不带外键的Span模型

Python Django中不带外键的Span模型,python,django,django-models,django-filter,Python,Django,Django Models,Django Filter,我使用的是Python2.7/Django 1.8,我有点像noob。我一直在用这两种型号创建过滤器: class A(models.Model): name = models.TextField() item_id = models.IntegerField() class B(models.Model): entry_id = models.AutoField(primary_key=True) active = models.BooleanFiel

我使用的是Python2.7/Django 1.8,我有点像noob。我一直在用这两种型号创建过滤器:

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)
 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
这有两次访问数据库的缺点,而且效率很低。有办法做到这一点吗?这些模型的设计是否应该有所不同


根据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\u id=2
的active设置为False,然后使用
active=True,id=3,parent=2
输入一个新值。DB设计方面,这是相当基本的东西

Django之所以变得复杂(特别是对于像我这样刚刚开始尝试围绕ORM思考的人来说),是因为用户角色是一种价值,我认为它们属于存储价值的应用程序。因此,
Authorization.user_root
指向一个id,该id是所有相关设置的父项

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

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

您的模型没有通过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)
有关更多信息,请参阅

例如,多对多关系的工作方式应该类似:

class A(models.Model):
    name = models.TextField()
    item_id = models.ManyToManyField(B,to_field='id')
此外,还不清楚您希望将
B
中的哪个
id
用作
外键,因此您实际上可能需要:

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

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

这是怎么回事?B的主键是
entry\u id
,但我需要特别谈谈
id
,它可能有多个条目。我是否只需要将其定义为
item\u id=models.ForeignKey(B,db\u column='id')
?本文讨论Django模型中的多对一关系,仅供参考:。您的猜测很接近,但应该使用
item\u id=models.ForeignKey(B,to\u field='id')
。如果
to_字段
为空,则假定主键是要链接的内容。希望有帮助!:)首先,谢谢你对我的帮助/支持。其次,这不起作用,因为
id
字段不是唯一的。因此,尝试创建迁移失败,因为“B.id”必须设置为unique=True,因为它被外键引用。但是,他们的整个问题是,可能有许多条目具有
id
。嗯,很抱歉,它不起作用。我建议使用实际的型号名称(如
Reporter
Article
,除非您为NSA工作)。它可以使事情变得更容易理解:)检查多对多关系:我还编辑了我的答案,以显示您将如何这样做。@f00f,实际上我认为这是因为您确实需要
item\u id=models.ForeignKey(B,through='entry\u id')
您的SQL查询示例与您的模型不匹配,所以这有点让人困惑。例如,在SQL查询中有
a.active=True
,但是
active
是模型中
B
上的一个字段。。。