使用unique_together具有相同ID的多个数据库对象

时间:2016-02-03 19:16:23

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

假设我有以下结构:

class Foo(models.Model):
    pass

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

我希望单个Bar对象同时键入自动递增ID Foo个对象。对于每个Foo,我希望下面的Bar始终为id 1,2,3。最终目标是通过URI访问Bar,例如:

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

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

我以为我在Foo课程的unique_together属性中找到了答案:

Meta

但遗憾的是,这仍然会为每个class Bar(models.Model): foo = models.ForeignKey(Foo, related_name='bars') class Meta: unique_together = ('foo', 'id') 生成一个唯一的ID。我总是希望每个Bar的第一个Bar ID为1。

2 个答案:

答案 0 :(得分:2)

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

一个天真的实现可能是这样的:

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)

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

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

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

答案 1 :(得分:0)

作为旁注,我实际上并不需要将此标识符存储在任何对象上。而不是

/foos/1/bars/1

导致查找Bar并将pk设置为1,我可以接受请求并返回类似

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

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

/foos/n/bars/m

使用主键m映射到Bar下的Foo n

丹尼尔的解决方案实际上回答了我原来的问题,所以我接受了这个问题。