[Fixed]-Fields and base_fields – Django


fields doesn’t exist until after you’ve called super. So just swap the order of the lines, so that super comes first.


A lesson from my own experience: modifying base_fields means that your modifications stick around "forever" (until python exits). In your case, that’s probably not a problem, as you are always using the same field name, and you are replacing its values with the assignment from ProjectTemplate…

In my case, I wanted completely different fields based on parameters in the constructor. Since my field names were usually different, each time I instantiated a form, I added new fields but didn’t eliminate the ones from the last time.

By calling super early (as indicated here) and then making my dynamic changes to self.fields instead of self.base_fields, I was able to eliminate the problem of an ever growing list of fields. It makes perfect sense now, but I wasn’t familiar with all of the syntax details and was hacking through instead of trying to understand it first.


In addition to Joe Germuska. If you truly need to change the form based on the request, you can use a deepcopy to make sure nothing is changed by reference:

def get_form(self, request, obj=None, **kwargs):
    form = super(ResourceAdmin, self).get_form(request, obj, **kwargs)
    form = copy.deepcopy(form)

    if obj:
        form.base_fields['email'] = EmailField(initial=obj.user.email)
    if not request.user.is_superuser:
        form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'})

    return form

Leave a comment