Django:使用不带ForeignKey字段的select_lated

Jos*_*eph 5 django django-models django-orm

我有两个模型与我无法控制的数据库一起使用。两者均设置为managed = False. 第一个模型有一个字段,它是第二个模型的外键,但它是作为 实现的CharField,而不是作为ForeignKey

是否可以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? 
Run Code Online (Sandbox Code Playgroud)

Goc*_*cht 1

不,因为没有任何关联。

但是,如果您(或出于某种原因的某人)存储了“相关”对象的 ID(或某些唯一值,例如localkey),则可以基于它执行过滤器。

foo = Foo.objects.first()  # Pick one Foo object
foo_bar = Bar.objects.get(localkey=foo.myfk)
Run Code Online (Sandbox Code Playgroud)

为了使它看起来像select_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
Run Code Online (Sandbox Code Playgroud)

然后像这样使用:

foos = Foo.objects.all()

for foo in foos:
    print foo.bar()
Run Code Online (Sandbox Code Playgroud)

我不确定这是否是一个好主意,但您可以将.bar()方法装饰为property

...

@property
def bar(self):
    return Bar.objects.get(localkey=self.myfk)
Run Code Online (Sandbox Code Playgroud)

然后这样称呼它:

foo  # some random Foo object
foo.bar  # this should return the 'related' Bar object
Run Code Online (Sandbox Code Playgroud)

  • 不过,在为每个“foos”实例获取“Bar”实例时,它会遇到额外的数据库查询。由于未捕获连接数据,因此它违背了使用“select_lated”的目的。我认为原始 sql 会更符合标准。 (2认同)
  • 并不是这个问题的真正答案。`select_lated` 向 `SELECT` 添加一个 `JOIN` 和一堆字段。其目的是“不”随后导致额外的数据库点击。这个答案将完全做到这一点 - 在访问其“.bar”属性(或方法)时,导致查询集中的每个对象发生数据库命中。 (2认同)