【问题标题】:ManyToMany through Queryset Django 2.2ManyToMany 通过 Queryset Django 2.2
【发布时间】:2019-06-17 08:28:05
【问题描述】:

我有 3 个模型及其关系:

class Itinerary(models.Model):
    origin_dest = models.CharField(max_length=200, blank=False, default="")
    travelers = models.ManyToManyField('Traveler')
    flights = models.ManyToManyField('Flight')

class Traveler(models.Model):
    pass

class Flight(models.Model):
    pass

一个行程包含一个或多个航班(经停与直达),并且一个航班可以属于多个行程。此外,一个旅行者可以有许多行程,而一个行程可以有许多旅行者。原因如下:

假设traveler 1 有一架从 JFK-LAX 起飞的航班,在 MIA 有 1 站。然后行程将有2个航班(JFK-MIA,MIA-LAX)。现在假设我们有另一个人,traveler 2,他的行程来自 MIA-LAX,与来自 MIA-JFK 的traveler 1 相同(不同的行程实例,但共享相同的航班)。因此,在这种情况下,有 2 个行程,其中一个航班 (MIA-LAX) 属于这两个行程,因此是 ManyToMany 关系。

现在,我最理想的做法是通过行程模型查询乘坐特定航班的所有旅客。大概是这样的:

flight.itinerary_set.travelers #=> return the number of travelers that are on that specific flight.

【问题讨论】:

  • 我认为它必须分两个阶段完成,第一个用于行程,第二个用于旅行者
  • 当然。我可以查询行程,然后为每个人抓住旅行者,但我想知道是否有一个很好的方法可以通过 Django 的 ORM 来做到这一点。

标签: python django orm


【解决方案1】:

您可能想要一个中间对象,例如Booking,这总是一个航班和一个旅行者。这样一来,就不会混淆哪个旅客在哪个航班上,这似乎是一个非常重要的区别,除非出于某种原因,这与您的用例无关。

该案例的示例模型:

from django.db import models


class Traveler(models.Model):
    name = models.TextField()

    def __str__(self):
        return self.name


class Flight(models.Model):
    number = models.TextField()

    def __str__(self):
        return self.number


class Itinerary(models.Model):
    pass


class Booking(models.Model):
    itinerary = models.ForeignKey(
        Itinerary,
        related_name='bookings',
        on_delete=models.CASCADE,
    )

    traveler = models.ForeignKey(
        Traveler,
        related_name='bookings',
        on_delete=models.CASCADE,
    )
    flight = models.ForeignKey(
        Flight,
        related_name='bookings',
        on_delete=models.CASCADE,
    )

测试用例的部分输出如下。请注意,这会在同一航班上创建两个单独的行程,并进行独立的预订。

>>> from itineraries.models import Traveler, Flight, Itinerary, Booking
>>> 
>>> f = Flight.objects.create(number='JAL1')
>>> 
>>> Booking.objects.create(
...     itinerary=Itinerary.objects.create(),
...     traveler=Traveler.objects.create(name='kungphu'),
...     flight=f,
... )
<Booking: Booking object (5)>
>>> 
>>> Booking.objects.create(
...     itinerary=Itinerary.objects.create(),
...     traveler=Traveler.objects.create(name='Cyzanfar'),
...     flight=f,
... )
<Booking: Booking object (6)>
>>> 
>>> # Travelers on flight f:
>>> for t in Traveler.objects.filter(bookings__flight=f):
...     print(t)
... 
kungphu
Cyzanfar

【讨论】:

  • 不客气!如果您觉得这很有用,请考虑接受答案。
  • 快速跟进。使用 django 聚合而不是创建另一个表会更有意义吗?
  • 我认为聚合不能真正起到同样的作用。您最初拥有的模型并不能明确知道哪个旅客在哪个航班上,因此如果这是您需要的信息,则必须至少进行一些关系调整才能实际保存该信息。
猜你喜欢
  • 2014-06-20
  • 1970-01-01
  • 2018-01-21
  • 2017-11-15
  • 1970-01-01
  • 2011-01-27
  • 2012-06-12
  • 2021-06-07
  • 2011-08-03
相关资源
最近更新 更多