Reputation: 1483
I'd like to add placeholder text to a field in the Django Admin change form. In a regular ModelForm you can do this by overriding the field's widget or by modifying self.fields['my_field'].widget
in the ModelForm __init__()
method. How do I do something similar for a Django Admin?
Upvotes: 2
Views: 4374
Reputation: 31
from django import forms
from django.contrib import admin
from django.contrib.admin.helpers import ActionForm
class CustomForm(ActionForm):
subject = forms.CharField(label='Label:', widget=admin.widgets.AdminTextInputWidget(attrs={'placeholder': 'my placeholder'}))
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
action_form = CustomForm
Upvotes: 1
Reputation: 1446
Another way to do this is:
class MyModelAdmin(model.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
#--> Get form
form = super().get_form(request, obj, **kwargs)
#--> Add placeholder for field
form.base_fields['the_field_name'].widget.attrs['placeholder'] = "My_Place_Holder_Text"
#--> Return form
return form
#---
#---
This is similar to the answer of dirkgroten. The advantage here is that there is no need to worry about the widget used for the field.
Upvotes: 1
Reputation: 4202
This is a way of doing it without having to manually add placeholder text to each field:
admin.py
from django import forms
class MyModelAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, *args, **kwargs):
form_instance = context['adminform'].form
for key, field in form_instance.fields.items():
if isinstance(field.widget, (forms.TextInput, forms.EmailInput)):
field.widget.attrs.update({'placeholder': field.label})
return super().render_change_form(request, context, *args, **kwargs)
Upvotes: 1
Reputation: 1483
Override the render_change_form()
method on your ModelAdmin, which provides access to the form instance:
class Address(model.Model):
street = models.CharField(max_length=50)
class AddressAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, *args, **kwargs):
form_instance = context['adminform'].form
form_instance.fields['street'].widget.attrs['placeholder'] = 'Your street'
return super().render_change_form(request, context, *args, **kwargs)
This approach would be the same for other field attributes like attributes like autocomplete
, autofocus
, min
, max
, required
, type
or pattern
. You also have access to context["original"]
which provides the model instance, in case you'd like to change the behavior based on the model instance.
The source code is the best reference for this: https://docs.djangoproject.com/en/2.2/_modules/django/contrib/admin/options/#ModelAdmin
Upvotes: 1
Reputation: 20702
The documented way is to override get_form()
:
The base implementation uses
modelform_factory()
to subclass form, modified by attributes such as fields and exclude.
If you look at the docs for modelform_factory you'll see that you can pass widgets
as kwarg. So this should work:
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
kwargs['widgets'] = {
'name': forms.TextInput(attrs={'placeholder': 'e.g. John Doe'})
}
return super().get_form(request, obj, **kwargs)
or, if you want to be sure you're not overriding any widgets (if you're inheriting from a subclass of ModelAdmin
):
kwargs['widgets'] = kwargs.get('widgets', {})
kwargs['widgets'].update({'name': ...})
Upvotes: 4