[Answered ]-Django forms passing request via get_form_kwargs fails to give form access to self.request.user

0👍

It appears I needed to get the current user (not just the request) using the form class’s __init__ method. Below is the views.py and forms.py code that ended up working:

views.py

# all necessary import statements

class MemberDetailView(
        LoginRequiredMixin, FormMixin,
        generic.DetailView, ProcessFormView
    ):
    """View class for member profile page"""
    model = User
    context_object_name = 'user'
    form_class = JoinCommunityForm
    success_url = '#communities-card'
    template_name = 'home/terpuser_detail.html'

    def get_queryset(self, *args, **kwargs):
        qs = super().get_queryset(*args, **kwargs)
        if not self.request.user.is_superuser:
            qs = qs.filter(pk=self.request.user.pk)
        return qs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(
            **kwargs,
            demo=get_object_or_404(Scenario.objects, scenario_id='demo'),
            today=date.today(),
        )
        return context
    
    def form_valid(self, form):
        # this is where I put my code to create a new Community membership object
        return super().form_valid(self, form)

forms.py

The line that ended up solving my problems is in the form class’s __init__ method: self.user = self.request.user. Then, I call self.user in the form class’s clean method rather than self.request.user

from communities.models import Community, UserRoleWithinCommunity

class JoinCommunityForm(forms.Form):
    pin = forms.RegexField(
                           '^[A-HJ-NP-Z1-9]$',
                           max_length=6, 
                           label='',
                           widget=forms.TextInput(attrs={
                               'oninput': 'this.value = this.value.toUpperCase()'
                                                        }
                                                  )
                           )

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None) # instantiate request kwarg as Willem suggests
        self.user = self.request.user # get user, this was key to resolving error
        super(JoinCommunityForm, self).__init__(*args, **kwargs)
    
    def clean(self):
        cleaned_data = super().clean()
        pin = self.cleaned_data['pin']
        test_join_code = f'{pin}'
        if Community.objects.filter(join_code=test_join_code).exists():
            # Make sure user is not already a member of the community
            communityToJoin = Community.objects.get(join_code=test_join_code)
            if UserRoleWithinCommunity.objects.filter(
                community=communityToJoin,
                user=self.user # here I call self.user instead of self.request.user
            ).exists():
                raise forms.ValidationError("You're already a member 
                                             of that Community")
            else:
                return cleaned_data
        else:
            raise forms.ValidationError("Join code is incorrect")

1👍

The reason this did not work is because you constructed the form with JoinCommunityForm(request.POST), whereas Django’s FormMixin will call get_form_kwargs() and then pass these to the form, as we can see in the source code [GitHub]:

def get_form(self, form_class=None):
    """Return an instance of the form to be used in this view."""
    if form_class is None:
        form_class = self.get_form_class()
    return form_class(**self.get_form_kwargs())

In your view you can however easily handle this with:

from django.views.generic.edit import FormMixin, ProcessFormView


class MemberDetailView(
    LoginRequiredMixin, FormMixin, generic.DetailView, ProcessFormView
):
    model = User
    context_object_name = 'user'
    form_class = JoinCommunityForm
    template_name = '…'  # template used in MemberDetailView

    def form_valid(self, form):
        # do something when the form is valid
        return super().form_valid(self, form)

Leave a comment