arlyon
arlyon

Reputation: 135

Reference multiple foreign keys in Django Model

I'm making a program that helps log missions in a game. In each of these missions I would like to be able to select a number of astronauts that will go along with it out of the astronauts table. This is fine when I only need one, but how could I approach multiple foreign keys in a field?

I currently use a 'binary' string that specifies which astronauts are to be associated with the mission (1 refers to Jeb, but not Bill, Bob, or Val and 0001 means only Val), with the first digit specifying the astronaut with id 1 and so forth. This works, but it feels quite clunky.

Here's the model.py for the two tables in question.

class astronauts(models.Model):
    name = models.CharField(max_length=200)
    adddate = models.IntegerField(default=0)
    experience = models.IntegerField(default=0)
    career = models.CharField(max_length=9, blank=True, null=True)
    alive = models.BooleanField(default=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "Kerbals"

class missions(models.Model):

    # mission details
    programid = models.ForeignKey(programs, on_delete=models.SET("Unknown"))
    missionid = models.IntegerField(default=0)
    status = models.ForeignKey(
        missionstatuses, on_delete=models.SET("Unknown"))
    plan = models.CharField(max_length=1000)

    # launch
    launchdate = models.IntegerField(default=0)
    crewmembers = models.IntegerField(default=0)

    # recovery
    summary = models.CharField(max_length=1000, blank=True)
    recdate = models.IntegerField(default=0)

    def __str__(self):
        return str(self.programid) + '-' + str(self.missionid)

    class Meta:
        verbose_name_plural = "Missions"

I saw a post about an 'intermediate linking table' to store the crew list but that also isn't ideal.

Thanks!

Upvotes: 0

Views: 1141

Answers (1)

Mark Ignacio
Mark Ignacio

Reputation: 431

This is the use case for Django's ManyToManyField. Change the appropriate field on the missions:

class missions(models.Model):
    crewmembers = models.ManyToManyField('astronauts')

You can access this from the Astronaut model side like so:

jeb = astronaut.objects.get(name='Jebediah Kerman')
crewed_missions = jeb.missions_set.all()

Or from the mission side like so:

mission = missions.objects.order_by('?')[0]
crew = mission.crewmembers.all()

This creates another table in the database, in case that is somehow a problem for you.

Upvotes: 1

Related Questions