0

I created models as below; Team model stores different team names, Tournament model is used to create a tournament and add teams into it and finally Game model where I select a tournament, add two teams and create a game. My problem is in Admin panel, while creating a game after selecting a tournament I have to select two teams from the choice list, instead of getting just the teams participating in the Tournament, I am getting all the available teams from the Team model.

class Team(models.Model):
    name = models.CharField(max_length=30) # Ind, Pak, Aus, Sri, Eng

class Tournament(models.Model):
    name = models.CharField(max_length=50) # Asia Cup:
    teams = models.ManyToManyField(Team)  # Ind, Pak, Sri

class Game(models.Model):
    name = models.CharField(max_length=50)
    tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE) # Asia Cup
    teams = models.ManyToManyField(Team) # Expected: Ind, Pak, Sri

My Admin panel customization:

class TeamInline(admin.TabularInline):
    model = Game.teams.through

class Game(admin.ModelAdmin):
    fields = ['name']
    inlines = [TeamInline]

enter image description here

Jitendra
  • 461
  • 6
  • 15

1 Answers1

0

Django Admin Inline use ModelForm to render it's content(described in doc) so you need to override the child form.

After that set custom formset to pass parent to child form, and in the child form override initial value with init within form doc

class TeamInlineCustomFormSet(BaseInlineFormSet):
    def get_form_kwargs(self, index):
        kwargs = super().get_form_kwargs(index)
        kwargs['parent_object'] = self.instance
        return kwargs

class TeamInlineCustomForm(forms.ModelForm):
    def __init__(self, *args, parent_object, **kwargs):
        self.parent_object = parent_object
        super (TeamInlineCustomForm, self).__init__(*args, **kwargs)
        if parent_object: # check if has game instance
            self.fields['team'].queryset = parent_object.tournament.teams.all()
       
    class Meta:
        model = Game.teams.through
        fields = ['team']

class TeamInline(admin.TabularInline):
    model = Game.teams.through
    
    formset = TeamInlineCustomFormSet
    form = TeamInlineCustomForm
  • this custom filtered queryset only work with edit form of the game(doesn't work on create game, it will show all teams)
  • parent_object refer to the Game instance when you editing

the way to get parent instance in Inline Admin Form come from this answer

Linh Nguyen
  • 3,452
  • 4
  • 23
  • 67
  • `django.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited; form TeamInlineCustomForm needs updating.` – Jitendra Aug 29 '22 at 11:49
  • @Jitendra i had updated my answer, just add fields to the ModelForm – Linh Nguyen Aug 30 '22 at 02:01