Reputation: 18923
In the Django admin, when the choice Custom
is selected from a dropdown list, I want to display the inline start_date
and end_date
fields to allow the user to specify a specific start and end-date instead of a pre-defined time period.
After researching for some time, suggestions include: use hidden fields, define override get_form in ModelAdmin, or use custom Javascript (which I have zero experience with).
The Question: how can I display (show) the inline start_date
and end_date
fields when a specific value (Custom
) is selected in the dropdown of a Django Admin field? When Custom
is not selected, start_date
and end_date
would be hidden from view.
Below is a complete example of the exact example code I have locally:
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
...
'dropdown.apps.DropdownConfig',
]
apps.py
from django.apps import AppConfig
class DropdownConfig(AppConfig):
name = 'dropdown'
models.py
from django.db import models
class DropdownModel(models.Model):
CHOICES = (
('Today', 'Today'),
('Yesterday', 'Yesterday'),
('Last 7 Days', 'Last 7 Days'),
('Last 14 Days', 'Last 14 Days'),
('Last 30 Days', 'Last 30 Days'),
('Last 60 Days', 'Last 60 Days'),
('Last 90 Days', 'Last 90 Days'),
('This Year', 'This Year'),
('All Time', 'All Time'),
('Custom', 'Custom')
)
date_range = models.CharField(max_length=15)
start_date = models.DateField()
end_date = models.DateField()
forms.py
from django import forms
from dropdown.models import DropdownModel
class DropdownModelForm(forms.ModelForm):
class Meta:
model = DropdownModel
fields = ('date_range',)
widgets = {
'date_range': forms.Select(choices=DropdownModel.CHOICES)
}
admin.py
from django.contrib import admin
from dropdown.models import DropdownModel
from dropdown.forms import DropdownModelForm
class DropdownModelAdmin(admin.ModelAdmin):
fieldsets = (
('Date Range', {
'fields': ('date_range', ('start_date', 'end_date'))
}),
)
form = DropdownModelForm
admin.site.register(DropdownModel, DropdownModelAdmin)
Upvotes: 22
Views: 13104
Reputation: 18923
Purpose of this question: to show / hide a fieldset if a specific option is selected in a Django admin form dropdown.
Solution overview: you need to break fieldsets up into two instead of one, custom javascript, define Media
class in ModelAdmin.
[Step One] In my project named dropdown
, I added the following folders / files:
[Step Two] In admin.py, a few things to note:
fieldsets
up into two instead of one.classes
for each fieldset. abcdefg
is the name of the class of the fieldset I'm trying to show and hide.class Media
. This tells django where to look for custom javascript and css files.admin.py
from django.contrib import admin
from dropdown.models import DropdownModel
from dropdown.forms import DropdownModelForm
class DropdownModelAdmin(admin.ModelAdmin):
fieldsets = (
('Date Range', {
'fields': ('date_range',),
'classes': ('predefined',)
}),
(None, {
'fields': (('start_date', 'end_date'),),
'classes': ('abcdefg',)
})
)
form = DropdownModelForm
class Media:
js = ('dropdown/js/base.js',)
admin.site.register(DropdownModel, DropdownModelAdmin)
[Step Three] Add javascript. I take no credit for this script; I only modified it slightly from here.
base.js
(function($) {
$(function() {
var selectField = $('#id_date_range'),
verified = $('.abcdefg');
function toggleVerified(value) {
if (value === 'Custom') {
verified.show();
} else {
verified.hide();
}
}
// show/hide on load based on existing value of selectField
toggleVerified(selectField.val());
// show/hide on change
selectField.change(function() {
toggleVerified($(this).val());
});
});
})(django.jQuery);
[Step Four]
forms.py
from django import forms
from dropdown.models import DropdownModel
class DropdownModelForm(forms.ModelForm):
class Meta:
model = DropdownModel
fields = ('date_range',)
widgets = {
'date_range': forms.Select(choices=DropdownModel.CHOICES)
}
Upvotes: 22