【问题标题】:Django finding which field matched in a multiple OR queryDjango 在多个 OR 查询中查找匹配的字段
【发布时间】:2012-09-17 07:42:49
【问题描述】:

我有几个模型是这样设置的:

class Bar(models.Model):
  baz = models.CharField()

class Foo(models.Model):
  bar1 = models.ForeignKey(Bar)
  bar2 = models.ForeignKey(Bar)
  bar3 = models.ForeignKey(Bar)

在代码的其他地方,我最终得到了一个 Bar 的实例,并且需要找到它以某种身份附加到的 Foo。现在我想出了使用 Q 进行多重 OR 查询,如下所示:

foo_inst = Foo.objects.get(Q(bar1=bar_inst) | Q(bar2=bar_inst) | Q(bar3=bar_inst))

我需要弄清楚的是,这 3 个案例中的哪一个实际命中,至少是成员的名称(bar1、bar2 或 bar3)。有没有好的方法来做到这一点?有没有更好的方法来构建查询以收集这些信息?

【问题讨论】:

  • bar1bar2bar3有什么区别?
  • 它们很可能指向不同的 Bar 实例!
  • 抱歉,bar1、bar2 和 bar3 都是独立的 Bar 实例。一个 Foo 将有 0-3 个不同的 Bars。

标签: python django model foreign-keys


【解决方案1】:
try:
    Foo.objects.get(bar1=bar_inst)
    print 'bar1'
except Foo.DoesNotExist:
    try:
        Foo.objects.get(bar2=bar_inst)
        print 'bar2'
    except Foo.DoesNotExist:
        try:
           Foo.objects.get(bar3=bar_inst)
           print 'bar3'
        except Foo.DoesNotExist:
           print 'nothing found'

还可以考虑将related_name 添加到模型的所有条形字段中。

【讨论】:

  • 我想这行得通,它有点 db 密集型,但也许我的设计只是问题所在......无论如何,目前的用例音量非常低,所以这可能会起作用,除非有什么更好的建议
【解决方案2】:

你可以改变一下并使用ChoiceField

BAR_VERSIONS = (
    ('Bar 1', 'bar1'),
    ('Bar 2', 'bar2'),
    ('Bar 3', 'bar3'),
)


class Bar(models.Model):
  baz = models.CharField()

class Foo(models.Model):
  bar = models.ForeignKey(Bar)
  bar_version = models.ChoiceField(choices=BAR_VERSIONS)

然后:

try:
    foo_instance = Foo.objects.get(bar=bar_instance)
except Foo.DoesNotExist:
    # Handle Exception
    pass
else:
    print(foo_instance.bar_version)

更新: 根据您的评论,由于我们的想法是不设置或全部设置bars,您仍然可以使用这种方法,但使用带有through 参数的ManyToManyField。如果您想添加 bar4 - barn 而不是扩展您的 try-except 瀑布,这将使它在未来变得更好和可扩展。

https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany

class Bar(models.Model):
  baz = models.CharField()

class Foo(models.Model):
  bars = models.ManyToManyField(bar, through='FooBars')

class FooBars(models.Model):
  foor = models.ForeignKey(Foo)
  bar = models.ForeignKey(Bar)
  bar_version = models.ChoiceField(choices=BAR_VERSIONS)

【讨论】:

  • 好选择已经出来了,因为可能会有数千个酒吧。但是“通过”设置可能会起作用,我会试一试
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2019-06-20
  • 2020-06-08
  • 1970-01-01
  • 2012-07-21
相关资源
最近更新 更多