简体   繁体   中英

How to customize/filter django admin panel forms data?

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]

在此处输入图像描述

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM