mike_gundy123
mike_gundy123

Reputation: 499

Access form 'fields' in django View class

I am trying to access the 'fields' attribute in my Class based View

Here's an example of what my forms.py looks like:

from django import forms
from .models import ErrorEvent


class ErrorEventForm(forms.ModelForm):

    class Meta:
        model = HumanErrorEvent
        # fields =
        exclude = ['event_id', 'user_modified', 'date_modified']
        widgets = {
            'owner': forms.TextInput(),
        }

Then here's my views:

class ErrorCreateView(CreateView):
    template_name = "forms/form.html"
    form_class = ErrorEventForm
    model = ErrorEvent

    def get_context_data(self, **kwargs):
        if not self.request.user.groups.filter(name='leaders').exists():
            self.form_class.fields['owner'].widget = forms.HiddenInput()
        context = super(ErrorCreateView, self).get_context_data(**kwargs)
        return context

The error I am getting is:

AttributeError: type object 'ErrorEventForm' has no attribute 'fields'

Due to this line:

self.form_class.fields['owner'].widget = forms.HiddenInput()

Is it not possible to access the 'fields' attribute in the views? If not, is there a way to hide the 'owner' form field based on the group the user is in?

Thank you for all your help in advance!

Upvotes: 1

Views: 1147

Answers (1)

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21787

The fields attribute of the form is only added when the form is instantiated the form class itself does not have it. Also get_context_data is not the best method to override for doing such things, a better method would perhaps be get_form, so you could write something like:

def get_form(self, form_class=None):
    form = super().get_form(form_class=form_class)
    form.fields['owner'].widget = forms.HiddenInput()
    return form

But we can still do better than this! Shouldn't such logic belong to the form class itself? Hence it would be better to simply pass the user to the form class. You can do this by overriding get_form_kwargs and the forms __init__ method:

# Form
class ErrorEventForm(forms.ModelForm):

    class Meta:
        model = HumanErrorEvent
        # fields =
        exclude = ['event_id', 'user_modified', 'date_modified']
        widgets = {
            'owner': forms.TextInput(),
        }
    
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        if user and not user.groups.filter(name='leaders').exists():
            del self.fields['owner']  # Remove the field itself from the form
            self.instance.owner = user  # Set the user as the owner


# View
class ErrorCreateView(CreateView):
    template_name = "forms/form.html"
    form_class = ErrorEventForm
    model = ErrorEvent
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

Upvotes: 1

Related Questions