【问题标题】:Django models' best solution for this reverse ForeignKeyDjango 模型对这个反向 ForeignKey 的最佳解决方案
【发布时间】:2020-01-05 23:54:05
【问题描述】:

我正在制作一个个人项目来管理餐厅。 我的两个模型面临一个问题,这些模型是 DiningRoom 和 Table。

DiningRoom 代表餐厅可能拥有的任何区域(例如,我们可以在建筑物内部拥有一个区域,而在建筑物的露台上拥有另一个区域)。 在每个 DiningRoom 中,我们可以设置 Tables 的布局。

因此,我发现映射它的更面向对象的方式是通过多对一关系 (ForeignKey)。由于一个 DiningRoom 可以有许多 Tables,而一个 Table 只能在一个 DiningRoom 中。对吧?

所以我的模型是:

class DiningRoom(models.Model):
    account = models.ForeignKey(Account, on_delete=models.CASCADE, null=False)
    name = models.CharField(max_length=50, null=False, blank=False)
    rows = models.IntegerField(max=15, null=False)
    cols = models.IntegerField(max=15, null=False)  # rows and columns are for the room's grid layout.


class Table(models.Model):
    row = models.IntegerField(max=15, null=False)  # The row in the room's grid where the table is at.
    col = models.IntegerField(max=15, null=False)  # the column in the room's grid where the table is at.
    dining_room = models.ForeignKey(DiningRoom, on_delete=models.CASCADE, null=False)  # Here is the problem.

问题是当我在视图中查询帐户的 DiningRooms 时,我还需要在查询集结果中获取与每个 DiningRoom 相关的表。

def dining_rooms(request):
    try:
        account = Account.objects.get(id=request.session['account_id'])
    except Account.DoesNotExists:
        return response(request, "error.html", {'error': 'Account.DoesNotExists'})

    dining_rooms = DiningRoom.objects.filter(account=account)

但我还需要dining_rooms 中的结果表!

我找到了两种可能的解决方案,但对我来说似乎没有一个是“正确的”。一种是建立多对多关系并验证任何 Table 仅在视图中的一个 DiningRoom 中。第二个更糟糕的可能是为查询集中获得的每个 DiningRoom 获取一次 Tables(但想象一个有 5 或 6 个不同区域(DiningRooms)的餐厅,每次都需要获取数据库六次)。

反之亦然并获取所有 Tables 和 select_related DiningRooms 是不可能的,因为可能有一个没有 Tables 的 DiningRoom(在这种情况下,我们将缺少 DiningRooms)。

处理此问题的最佳方法是什么?谢谢!

【问题讨论】:

  • 你可以执行.prefetch_related,它只会做一个额外的查询,并在Django/Python级别进行“JOIN”。
  • @WillemVanOnsem 我不明白。如果我这样做 DiningRoom.objects.filter(account=account).prefetch_related('tables') 这是一个属性错误。什么意思?
  • 据我所知,如果我要通过表查询,我可以使用 .prefetch_related ......但它是相反的......你能解释一下吗?

标签: python django django-queryset many-to-one


【解决方案1】:

您可以向后使用related_name 或关系,一个可接受的解决方案是在DiningRoom 模型中创建一个名为 associated_tables() 的方法并使用related_name(modelname_set,在本例中为table_set)返回。它是小写子模型的名称,后跟_set

class DiningRoom(models.Model):
    #your fields

    def associated_tables(self):
        return self.table_set.all()

此外,此视频教程可以让您清空并让您更好地了解反向关系: https://youtu.be/7tAZdYRA8Sw

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多