Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Admin Show / Hide Fields If Specific Value Is Selected In A Dropdown

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.


Step 1: step 1 - select a date range

Step 2: step 2 - if custom is selected

Step 3: step 3 - show the inline custom date fields


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)
like image 269
Jarad Avatar asked Dec 15 '17 18:12

Jarad


People also ask

How do I hide a field in Django admin panel?

For the admin list-view of the items, it suffices to simply leave out fields not required: e.g. In Django 1.8 exclude = ('fieldname',) does works with admin. ModelAdmin so one does not have to inherit from InlineModelAdmin anymore. Also works in Django 1.6.

What does admin do in Django?

The Django admin application can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the right data.

What does manage PY do in Django?

In addition, manage.py is automatically created in each Django project. It does the same thing as django-admin but also sets the DJANGO_SETTINGS_MODULE environment variable so that it points to your project's settings.py file.


1 Answers

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:

  • static (directory)
  • static/dropdown (directory)
  • static/dropdown/js (directory)
  • static/dropdown/js/base.js (file)

[Step Two] In admin.py, a few things to note:

  1. I broke fieldsets up into two instead of one.
  2. Notice that I'm defining classes for each fieldset. abcdefg is the name of the class of the fieldset I'm trying to show and hide.
  3. I defined 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)
        }
like image 170
Jarad Avatar answered Oct 11 '22 14:10

Jarad