[Django]-Adding new form fields dynamically in admin

3👍

When rendering your form in template, fields enumerating from fieldsets variable, not from fields. Sure you can redefine fieldsets in your AdminForm, but then validations will fail as original form class doesn’t have such field. One workaround I can propose is to define this field in form definition statically and then redefine that field in form’s init method dynamically. Here is an example:

class ServiceRoleAssignmentForm(forms.ModelForm):
    test = forms.Field()

    class Meta:
        model = ServiceRoleAssignment

    def __init__(self, *args, **kwargs):
        super(ServiceRoleAssignmentForm, self).__init__(*args, **kwargs)
        # Here we will redefine our test field.
        self.fields['test'] = forms.CharField(label='test2')
👤Oleg

0👍

I actually have a the same issue which I’m working through at the moment.
While not ideal, I have found a temporary workaround that works for my use case. It might be of use to you?

In my case I have a static name for the field, so I just declared it in my ModelForm. as normal, I then override the init() as normal to override some options.

ie:

def statemachine_form(for_model=None):
    """
    Factory function to create a special case form
    """
    class _StateMachineBaseModelForm(forms.ModelForm):
        _sm_action = forms.ChoiceField(choices=[], label="Take Action")

        class Meta:
            model = for_model

        def __init__(self, *args, **kwargs):
            super(_StateMachineBaseModelForm, self).__init__(*args, **kwargs)
            actions = (('', '-----------'),)
            for action in self.instance.sm_state_actions():
                actions += ((action, action),)
            self.fields['_sm_action'] = forms.ChoiceField(choices=actions,
                                                          label="Take Action")
    if for_model: return _StateMachineBaseModelForm

class ContentItemAdmin(admin.ModelAdmin):
    form = statemachine_form(for_model=ContentItem)

Now as I mentioned before, this is not entirely ‘dynamic’, but this will do for me for the time being.

I have the exact same problem that, if I add the field dynamically, without declaring it first, then it doesn’t actually exist. I think this does in fact have something to do with the way that ModelForm creates the fields.

I’m hoping someone else can give us some more info.

👤Andre

0👍

👤Googol

-2👍

Try to add the field before calling the super.init:

def __init__(self, *args, **kwargs):
    self.fields['test'] = forms.CharField(label='test') 
    super(ServiceRoleAssignmentForm, self).__init__(*args, **kwargs)

Leave a comment