如果在下拉列表中选择了特定值,则 Django 管理员显示/隐藏字段

2022-01-25 00:00:00 python django django-admin django-forms

问题描述

在 Django 管理员中,当从下拉列表中选择 Custom 选项时,我想显示内联 start_dateend_date 字段允许用户指定特定的开始和结束日期,而不是预定义的时间段.

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.

经过一段时间的研究,建议包括:使用隐藏字段,在ModelAdmin中定义覆盖get_form,或者使用自定义Javascript(我零经验).

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).

问题:当特定值(Custom) 在 Django Admin 字段的下拉列表中被选中?未选择 Custom 时,start_dateend_date 将隐藏在视图中.

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.

第 1 步:

第 2 步:

第 3 步:

以下是我在本地拥有的确切示例代码的完整示例:

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)


解决方案

此问题的目的:如果在 Django 管理表单下拉列表中选择了特定选项,则显示/隐藏字段集.

Purpose of this question: to show / hide a fieldset if a specific option is selected in a Django admin form dropdown.

解决方案概述:您需要将字段集分成两个而不是一个,自定义 javascript,在 ModelAdmin 中定义 Media 类.

Solution overview: you need to break fieldsets up into two instead of one, custom javascript, define Media class in ModelAdmin.

[第一步]在我的名为dropdown的项目中,我添加了以下文件夹/文件:

[Step One] In my project named dropdown, I added the following folders / files:

  • 静态(目录)
  • 静态/下拉(目录)
  • static/dropdown/js(目录)
  • static/dropdown/js/base.js(文件)

[第二步]在admin.py中,有几点需要注意:

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

  1. 我将 fieldsets 分成两部分而不是一部分.
  2. 请注意,我正在为每个字段集定义 classes.abcdefg 是我要显示和隐藏的字段集的类的名称.
  3. 我定义了 class Media.这告诉 django 在哪里寻找自定义的 javascript 和 css 文件.
  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)

[第三步] 添加javascript.我不相信这个剧本;我只是从这里稍微修改了一下.

[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);

[第四步]

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)
        }

相关文章