ManyToMany через Queryset Django 2.2 - PullRequest
0 голосов
/ 16 июня 2019

У меня есть 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, который имеет 1 остановку в МВД.Тогда маршрут будет иметь 2 рейса (JFK-MIA, MIA-LAX).Теперь предположим, что у нас есть еще один человек, traveler 2, у которого есть маршрут из MIA-LAX, который совпадает с рейсом traveler 1, идущим из MIA-JFK (другой экземпляр маршрута, но тот же общий рейс).Таким образом, в этом случае есть 2 маршрута, в которых один рейс (MIA-LAX) принадлежит этим двум маршрутам, следовательно, отношение ManyToMany.

Теперь, в идеале, я хотел бы сделать запрос всем путешественникам, которыена конкретный рейс через маршрутную модель.Примерно так:

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

1 Ответ

1 голос
/ 17 июня 2019

Возможно, вы захотите иметь промежуточный объект, например, 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...