Reputation: 7136
I have 3 models and their relation:
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
An Itinerary has one or many flights (stop vs nonstop) and a flight can belong to more than one itinerary. Also, a traveler can have many itineraries and an itinerary can have many travelers. Here is why:
Let's say traveler 1
has a flight from JFK-LAX which has 1 stop in MIA. Then the Itinerary will have 2 flights (JFK-MIA, MIA-LAX). Now let's say we have another person, traveler 2
who has an itinerary from MIA-LAX which is the same flight as traveler 1
going from MIA-JFK (different itinerary instance but same flight shared). Therefore in this case, there are 2 itinerary where a single flight (MIA-LAX) belongs to those two itineraries, hence the ManyToMany relationship.
Now what I'd like to do ideally is query all travelers that are on a particular flight through the itinerary model. Somethind like this:
flight.itinerary_set.travelers #=> return the number of travelers that are on that specific flight.
Upvotes: 0
Views: 246
Reputation: 4849
You might want to have an intermediate object, e.g. Booking
, that's always a single flight and a single traveler. That way there's no potential for confusion regarding which traveler is on which flight, which seems like a pretty important distinction, unless for some reason that's not relevant in your use case.
Example models for that case:
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,
)
Partial output from test case is below. Note that this creates two separate itineraries with independent bookings on the same flight.
>>> 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
Upvotes: 1