Search code examples
pythondjangowidgetdjango-adminoverriding

Django Admin - Overriding the widget of a custom form field


I have a custom TagField form field.

class TagField(forms.CharField):
    def __init__(self, *args, **kwargs):
        super(TagField, self).__init__(*args, **kwargs)
        self.widget = forms.TextInput(attrs={'class':'tag_field'})

As seen above, it uses a TextInput form field widget. But in admin I would like it to be displayed using Textarea widget. For this, there is formfield_overrides hook but it does not work for this case.

The admin declaration is:

class ProductAdmin(admin.ModelAdmin):
    ...
    formfield_overrides = {
        TagField: {'widget': admin.widgets.AdminTextareaWidget},
    }

This has no effect on the form field widget and tags are still rendered with a TextInput widget.

Any help is much appreciated.

--
omat


Solution

  • The django admin uses custom widgets for many of its fields. The way to override fields is to create a Form for use with the ModelAdmin object.

    # forms.py
    
    from django import forms
    from django.contrib import admin
    
    class ProductAdminForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super(ProductAdminForm, self).__init__(*args, **kwargs)
            self.fields['tags'].widget = admin.widgets.AdminTextareaWidget()
    

    Then, in your ModelAdmin object, you specify the form:

    from django.contrib import admin
    from models import Product
    from forms import ProductAdminForm
    
    class ProductAdmin(admin.ModelAdmin):
        form = ProductAdminForm
    
    admin.site.register(Product, ProductAdmin)
    

    You can also override the queryset at this time: to filter objects according to another field in the model, for instance (since limit_choices_to cannot handle this)