4

I want to be able to add fields to django admin form at runtime. My model and form:

#admin.py
class SitesForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(SitesForm, self).__init__(*args, **kwargs)

        self.fields['mynewfield'] = forms.CharField()

class SitesAdmin(admin.ModelAdmin):
    form = SitesForm

admin.site.register(Sites,SitesAdmin)

#model.py
class Sites(models.Model):
    url = models.URLField(u'URL')
    is_active = models.BooleanField(default=True, blank=True)
    is_new = models.BooleanField(default=False, blank=True)
    group = models.ForeignKey('SitesGroup')
    config = models.TextField(blank=True)

Field mynewfield isn't displayed in form. Why?

Vadym
  • 1,444
  • 21
  • 37

2 Answers2

3

You shouldn't be adding a new field to your form in that way, you can just do it as you would any other field and the form will contain both the Model's original fields and your new fields:

class SitesForm(forms.ModelForm):
  mynewfield = forms.CharField(max_length=255, blank=True)

  class Meta:
    model = Sites

class SitesAdmin(admin.ModelAdmin):
  form = SitesForm

admin.site.register(Sites, SitesAdmin)

Edit: Sorry, should have read what you had written a little better. If you want a dynamic field like that, then you need to do the following and it will do exactly what you want:

class SitesForm(forms.ModelForm):
  class Meta:
    model = Sites

  def __init__(self, *args, **kwargs):
    self.base_fields['mynewfield'] = forms.CharField(max_length=255, blank=True)
    super(SitesForm, self).__init__(*args, **kwargs)

class SitesAdmin(admin.ModelAdmin):
  form = SitesForm

admin.site.register(Sites, SitesAdmin)

It's the base_fields that gets composed by the metaclass that holds the fields that the form will use.

Dominic Santos
  • 1,900
  • 12
  • 14
3

Solution:

class AdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AdminForm, self).__init__(*args, **kwargs)
        self.fields.insert(1, 'myfield', forms.CharField())

class MyAdmin(admin.ModelAdmin):
    form = AdminForm

    def get_fieldsets(self, request, obj=None):
        return (
            (None, {
                'fields': (..., 'myfield',),
            }),
        )
Vadym
  • 1,444
  • 21
  • 37