【问题标题】:Multiple database objects with the same ID using unique_together使用 unique_together 具有相同 ID 的多个数据库对象
【发布时间】:2016-05-13 03:54:57
【问题描述】:

假设我有以下结构:

class Foo(models.Model):
    pass

class Bar(models.Model):
    foo = models.ForeignKey(Foo, related_name='bars')

我希望单个 Bar 对象在自动递增 ID Foo 对象上都被键入。对于每个Foo,我希望下面的Bars 始终是1,2,3。最终目的是通过 URI 访问Bars,例如:

/foos/1/bars/1
/foos/2/bars/1

请注意,有两个 Bars 具有相同的 ID,但主键来自 Bar 及其父 Foo 的 ID 的唯一性。

我以为我在Meta 类的unique_together 属性中找到了答案:

class Bar(models.Model):
    foo = models.ForeignKey(Foo, related_name='bars')

    class Meta:
        unique_together = ('foo', 'id')

但不幸的是,这仍然会导致每个 Bar 的唯一 ID。我总是希望每个 Foo 的第一个 Bar 的 ID 为 1。

【问题讨论】:

    标签: python sql django django-models django-rest-framework


    【解决方案1】:

    您不能使用 ID 执行此操作,因为它是由数据库分配的,并且在整个表中始终是唯一的。如果你真的想要这个,你必须定义一个单独的字段,并在每次为你的 foo 创建一个 bar 时增加它。

    一个简单的实现可能是这样的:

    class Bar(models.Model):
        foo_order = models.IntegerField()
        foo = models.ForeignKey(Foo, related_name='bars')
    
        class Meta:
            unique_together = ('foo', 'foo_order')
    
        def save(self, *args, **kwargs):
            if not self.foo_order:
                self.foo_order = self.bar_set.count() + 1
            super(Bar, self).save(*args, **kwargs)
    

    (请注意,这可能会受到各种竞争条件的影响,所以要小心。)

    现在您可以使用视图中的字段组合来获取相关的 Bar:

    def bar_view(request, foo_id, order):
        my_bar = Bar.objects.get(foo_id=foo_id, foo_order=order)
    

    【讨论】:

    • 谢谢。我想我认为 id 和 pk 字段有问题 - pk 将是底层的、每个表唯一的值,而 id 没有这样的约束。您的解决方案是有道理的,但是是的 - 绝对必须小心这样做。我很惊讶没有内置的方法来做到这一点,更何况如果其他人还没有为它实现一个库。再次干杯!
    【解决方案2】:

    附带说明,我实际上不需要将此标识符存储在任何对象上。而不是

    /foos/1/bars/1
    

    导致在 pk 设置为 1 的情况下查找 Bar,我可以接受请求并返回类似的内容

    Foo.objects.get(id=1).bars.all()[0]
    

    即从而映射到第一个 Bar。所以

    /foos/n/bars/m
    

    映射到Foo 下的mth Bar,主键为n

    Daniel 的解决方案实际上回答了我最初的问题,所以我接受它作为答案。

    【讨论】:

      猜你喜欢
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 2013-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多