【发布时间】: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