4

I am trying to add dynamically new form fields (I used this blog post), for a form used in admin interface :

class ServiceRoleAssignmentForm(forms.ModelForm):

    class Meta:
        model = ServiceRoleAssignment

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


class ServiceRoleAssignmentAdmin(admin.ModelAdmin):
    form = ServiceRoleAssignmentForm

admin.site.register(ServiceRoleAssignment, ServiceRoleAssignmentAdmin)

However, no matter what I try, the field doesn't appear on my admin form ! Could it be a problem related to the way admin works ? Or to ModelForm ?

Thank for any help !

Sébastien

PS : I am using django 1.3

4 Answers 4

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')
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer ! I was thinking about doing that actually ... But I didn't get this part "fields enumerating from fieldsets variable, not from fields. Sure you can redefine fieldsets in your AdminForm". What's that fieldsets variable ? You mean that there is a "fields" variable that contains all fields, and a "fieldsets" that is used for rendering them ? In that case why not adding the new field to both "fieldsets" AND "fields" ???
Have a look at the template. You might want to override the template (or update it if you're already overriding it).
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.

2 Comments

oh you may notice I'm using a factory function to generate the form. This is part of me trying to find the solution. I ran across docs on this here: b-list.org/weblog/2008/nov/09/dynamic-forms
Well ... that could work indeed ! I could for example declare 10 useless fields with hidden input, and then "toggle them on" dynamically ... But that's not very beautiful. Thanks for this workaround ! For the moment, I will just go-on with declaring the fields statically ...
0

Django - Overriding get_form to customize admin forms based on request

Comments

-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)

1 Comment

The fields attribute doesn't exist until after you call super on the form.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.