[Fixed]-Fields and base_fields – Django

17👍

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

16👍

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.

4👍

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