Pietro Pietro - 4 months ago 36
Python Question

Django 1.9 FormView never reach get_context_data

I have a FormView called LeagueTransferView based on a form LeagueTransferForm.

I'm trying to override get_context_data to add extra players to render in the template.

But get_context_data is never reached. It's working fine on other views like, DetailView, ListView,...

I'm missing something?

Below my configuration

View

class LeagueTransferView(FormView):
template_name = 'hockey/league/transfer_market.html'
form_class = LeagueTransferForm
success_url = ''

def get_context_data(self, **kwargs):
print('----NEVER REACHED----')
context = super(LeagueTransferView, self).get_context_data(**kwargs)
petitioner = get_object_or_404(Team, user=self.request.user.profile, league=self.kwargs['pk'])
context['players'] = Player.objects.filter(leagues=self.kwargs['pk']).exclude(teams=petitioner)
return context

def get(self, request, *args, **kwargs):
petitioner = get_object_or_404(Team, user=self.request.user.profile, league=self.kwargs['pk'])
form = self.form_class(initial={'league': self.kwargs['pk'], 'petitioner': petitioner})
form.fields['offered_player'].queryset = petitioner.players
return render(request, self.template_name, {'form': form})

def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
transfer = form.save(commit=False)
team = Team.objects.filter(league=transfer.league, players__in=[transfer.requested_player])
if not team: # free agent
transfer.status = 1
messages.success(request, _('transfer succeeded'))
else:
print(team)
transfer.player_owner = team[0]
if transfer.petitioner.user is None: # bot team
transfer.status = 1
messages.success(request, _('transfer succeeded'))
else:
messages.success(request, _('transfer waiting for confirmation by player owner'))
transfer.save()
return HttpResponseRedirect(reverse('hockey_dashboard'))

petitioner = get_object_or_404(Team, user=self.request.user.profile, league=self.kwargs['pk'])
form.fields['offered_player'].queryset = petitioner.players
return render(request, self.template_name, {'form': form})


FORM

class LeagueTransferForm(forms.ModelForm):
class Meta:
model = Transfer
fields = ['league', 'requested_player', 'offered_player', 'player_owner', 'petitioner']
labels = {
'requested_player': _('Requested player'),
'offered_player': _('Offered player'),
}
widgets = {
'requested_player': forms.HiddenInput,
'league': forms.HiddenInput,
'player_owner': forms.HiddenInput,
'petitioner': forms.HiddenInput
}

Answer

Your code is never reaching get_context_data() because you have overridden the get() method and not calling the get_context_data() function there. You need to manually call the get_context_data() function at the time of passing context to render() in your code.

Instead of doing that, i would suggest you to try the below approach where instead of overrriding get() and returning your custom response, you only override what is necessary and let Django handle the rest.

class LeagueTransferView(FormView):
    template_name = 'hockey/league/transfer_market.html'
    form_class = LeagueTransferForm
    success_url = ''

    def get_context_data(self, **kwargs):
        context = super(LeagueTransferView, self).get_context_data(**kwargs)
        context['players'] = Player.objects.filter(leagues=self.kwargs['pk']).exclude(teams=self.petitioner)
        return context

    def get_initial(self):
        initial = super(LeagueTransferView, self).get_initial()
        initial['league'] = self.kwargs['pk'] # add custom data to initial
        initial['petitioner'] = self.petitioner # add custom data to initial
        return initial

    def get_form(self, form_class=None):
        form = super(LeagueTransferView, self).get_form(form_class)
        # override the queryset
        form.fields['offered_player'].queryset = self.petitioner.players 
        return form

    def get(self, request, *args, **kwargs):
        # only perform 1 query to get 'petitioner'
        self.petitioner = get_object_or_404(Team, user=self.request.user.profile, league=self.kwargs['pk'])
        return super(LeagueTransferView, self).get(request, *args, **kwargs)