Django:使用无外键字段的select_related
我有两个模型,它们与我不控制的数据库一起使用。两者都设置为Django:使用无外键字段的select_related,django,django-models,django-orm,Django,Django Models,Django Orm,我有两个模型,它们与我不控制的数据库一起使用。两者都设置为managed=False。第一个模型有一个字段,该字段是第二个模型的外键,但它被实现为字符字段,而不是外键 是否可以在第一个模型上使用select_related,以访问第二个模型的关键属性 下面是一个例子: class Foo(models.Model): class Meta: managed = False fieldone = models.CharField(max_length=10)
managed=False
。第一个模型有一个字段,该字段是第二个模型的外键,但它被实现为字符字段
,而不是外键
是否可以在第一个模型上使用select_related
,以访问第二个模型的关键属性
下面是一个例子:
class Foo(models.Model):
class Meta:
managed = False
fieldone = models.CharField(max_length=10)
myfk = models.CharField(max_length=20) # In practice, this points to Bar.localkey
class Bar(models.Model):
class Meta:
managed = False
localkey = models.CharField(max_length=20)
someotherattribute = models.CharField(max_length=100)
Foo.objects.all().select_related('Bar') # I know this won't work, but is there something that will?
没有,因为没有什么相关的 但是,如果您(或某些人出于某种原因)存储了来自“相关”对象的ID(或某些唯一值,如
localkey
),则可以基于它执行筛选
foo = Foo.objects.first() # Pick one Foo object
foo_bar = Bar.objects.get(localkey=foo.myfk)
要使其看起来像选择\u related
,您可以尝试以下方法:
class Foo(models.Model):
class Meta:
managed = False
fieldone = models.CharField(max_length=10)
myfk = models.CharField(max_length=20)
def bar(self):
return Bar.objects.get(localkey=self.myfk)
# probably you will need to manage common error when performing a .get()
# DoesNotExist and MultipleObjectsReturned
然后像这样使用:
foos = Foo.objects.all()
for foo in foos:
print foo.bar()
foo # some random Foo object
foo.bar # this should return the 'related' Bar object
我不确定这是否是个好主意,但您可以将.bar()
方法装饰为:
然后这样称呼它:
foos = Foo.objects.all()
for foo in foos:
print foo.bar()
foo # some random Foo object
foo.bar # this should return the 'related' Bar object
为什么不能使用
ForeignKey
?我想我不能使用ForeignKey,因为这个模型使用的实际数据库超出了我的控制(因此managed=False
)。然而,即使这种关系没有在该数据库中实现为真正的外键,在这里使用外键似乎确实有效,我现在可以使用select\u related
。但是,在为foos
的每个实例获取Bar
的实例时,它会遇到额外的db查询。它违背了使用select\u related
的目的,因为连接数据未被捕获。我认为原始sql应该更符合标准。这并不是这个问题的答案select\u related
向select
添加一个JOIN
和一组字段。这样做的目的是在以后不会造成额外的DB点击。这个答案正好可以做到这一点——在访问queryset的.bar
属性(或方法)时,会导致queryset中的每个对象的DB命中。