dotty
dotty

Reputation: 41433

Django admin, limiting what data is being displayed inside a ManyToManyField

i have 3 models Team, Player and Fixture.

Fixture

class Fixture(models.Model):
    """(Fixture description)"""
    home = models.ForeignKey(Team, related_name="home_games")
    away = models.ForeignKey(Team, related_name="away_games")
    home_players = models.ManyToManyField(Player, related_name="home_games")
    away_players = models.ManyToManyField(Player, related_name="away_games")

class Player(models.Model):
    """(Player description)"""
    surname = models.CharField(blank=True, max_length=255)
    forename = models.CharField(blank=True, max_length=255)
    number = models.IntegerField(blank=True, null=True)
    team = models.ForeignKey(Team, related_name="players")

class Team(models.Model):
    """(Team description)"""
    name = models.CharField(blank=True, max_length=255)
    location = models.CharField(blank=True, max_length=255) 

As you can see a player belongs to a team. The Fixture as a home_team, away_team, home_players and away_players. Now, within the admin, under fixtures the "home_players" is listing ALL players, from all teams.

I'm kind of new to the django admin application, but how would i just show the home_players belonging to the home_team and the away_players belonging to the away_teams?

Thanks

Upvotes: 0

Views: 305

Answers (1)

To have your away_players field automatically update itself as you select the home or away team you'd need to use JavasScript.

  1. Listen for change event on away_team
  2. Send a view the selection and have it return a new list to populate your away_players field. (check get_urls for where this code might live)

It's definitely not supported out of the box.

Normally to filter the results on a m2m field or foreign key, you can use formfield_for_manytomany, but it doesn't have access to the object being edited so I don't think it's possible through this method.

I think the easiest solution is to make the form 2 stage:

  1. Fill in home/away fields
  2. Save model
  3. Fill in home/away players

You could also override the admin add view to only show the first two fields at first.

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        # make sure we're editing a saved model
        if self.instance.id:
            self.fields['home_players'].queryset = Player.objects.filter(team=self.instance.home)
            self.fields['away_players'].queryset = Player.objects.filter(team=self.instance.away)

    class Meta:
        model = Fixture


class MyAdmin(admin.ModelAdmin):
    form = MyForm

Upvotes: 2

Related Questions