简体   繁体   English

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

[英]Django Admin Panel: Show/Hide Fields If Specific Value Is Selected In A Dropdown

What am I doing wrong?我究竟做错了什么?
In django admin-panel I want to show/hide field(s) based on the choice dropdown.在 django 管理面板中,我想根据选择下拉列表显示/隐藏字段。 Also the, choice dropdown lies on parent foreign-key related model and the fields that are to be shown/hidden lies in child model or as an stacked inline.此外,选择下拉列表位于与父外键相关的 model 中,要显示/隐藏的字段位于子 model 中或作为堆叠内联。
I've followed this solution(stack overflow) , but no success.我遵循了这个解决方案(堆栈溢出) ,但没有成功。

models.py模型.py

from django.db import models

CHOICES = (
        ('video', 'Video'),
        ('text', 'Text'),
        ('question', 'Question'),
)


class Section(models.Model):
    content_type = models.CharField(max_length=32)

    @property
    def contents(self):
        return self.content_set.all()

class Content(models.Model):
    content = models.ForeignKey(Section, on_delete=models.DCASCADE)
    video = models.FileField()
    text = models.TextField()
    question = models.CharField(max_length=512)

admin.py管理员.py

from django.contrib import admin

from .models import Section, Content
from .forms import DropdownModelForm


class ContentInline(admin.StackedInline):
    model = Content
    fieldsets = (
        (None, {
            'fields': (('video',),),
            'classes': ('vid',)
        }),
        (None, {
            'fields': (('text',),),
            'classes': ('txt',)
        }),
        (None, {
            'fields': (('question',),),
            'classes': ('ques',)
        })
    )

    class Media:
        js = ('one/js/base.js',)

@admin.register(Section)
class SectionAdmin(admin.ModelAdmin):
    form = DropdownModelForm
    inlines = (ContentInline,)

forms.py forms.py

from django import forms
from .models import Section, CHOICES

class DropdownModelForm(forms.ModelForm):

    class Meta:
        model = Section
        fields = ('content_type',)
        widgets = {
            'content_type': forms.Select(choices=CHOICES)
        }

base.js基础.js

(function($) {
    $(function() {
        var selectField = $('#id_content_type'),
            verified_1 = $('.vid'),
            verified_2 = $('.txt'),
            verified_3 = $('.ques');

        function toggleVerified(value) {
            if (value === 'video') {
                verified_1.show();
                verified_2.hide();
                verified_3.hide();
            } else if (value === 'text') {
                verified_1.hide();
                verified_2.show();
                verified_3.hide();
            } else if (value === 'question') {
                verified_1.hide();
                verified_2.hide();
                verified_3.show();
            }
        }

        // show/hide on load based on pervious value of selectField
        toggleVerified(selectField.val());

        // show/hide on change
        selectField.change(function() {
            toggleVerified($(this).val());
        });
    });
})(django.jQuery);

settings.py设置.py

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
.
.
.

INSTALLED_APPS = [
    'one.apps.OneConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
.
.
.

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / "static",
]

项目结构

Again, What am I doing wrong?再一次,我做错了什么?
In django admin-panel I want to show/hide field(s) based on the choice dropdown.在 django 管理面板中,我想根据选择下拉列表显示/隐藏字段。 Also the, choice dropdown lies on parent foreign-key related model and the fields that are to be shown/hidden lies in child model or as an stacked inline.此外,选择下拉列表位于与父外键相关的 model 中,要显示/隐藏的字段位于子 model 中或作为堆叠内联。
I've followed this solution(stack overflow) , but no success.我遵循了这个解决方案(堆栈溢出) ,但没有成功。

Thank you very much for expending your valuable time & giving a look on my poor code非常感谢您花费宝贵的时间并查看我糟糕的代码

passing javascript file as a list in admin.py solved the problem.javascript文件作为 admin.py 中的列表admin.py解决了该问题。

class Media:
        js = ["one/js/base.js",]

also, don't know why jquery was not working properly.另外,不知道为什么 jquery 不能正常工作。 So for this wrap your javascript inside jQuery(document).ready(function ($) {...your javascript... });因此,为此将您的javascript包装在jQuery(document).ready(function ($) {...your javascript... }); , as , 作为

jQuery(document).ready(function ($) {
    (function ($) {
        $(function () {
            var selectField = $('#id_content_type'),
                verified_1 = $('.vid'),
                verified_2 = $('.txt'),
                verified_3 = $('.ques');

            function toggleVerified(value) {
                if (value === 'video') {
                    verified_1.show();
                    verified_2.hide();
                    verified_3.hide();
                } else if (value === 'text') {
                    verified_1.hide();
                    verified_2.show();
                    verified_3.hide();
                } else if (value === 'question') {
                    verified_1.hide();
                    verified_2.hide();
                    verified_3.show();
                }
            }

            // show/hide on load based on pervious value of selectField
            toggleVerified(selectField.val());

            // show/hide on change
            selectField.change(function () {
                toggleVerified($(this).val());
            });
        });
    })(django.jQuery);
});

If anyone ever encounters the same problem as me and doesn't know JS, here is my case and solution.如果有人遇到过和我一样的问题并且不了解 JS,这是我的案例和解决方案。

Case: Need to create courses in django admin site with possible formats online/offline and if format is offline field city is showed.案例:需要在 django 管理站点中创建具有可能的online/offline格式的课程,如果formatoffline ,则显示字段city

Solution:解决方案:

models.py模型.py

class Course(models.Model):
    FORMAT_CHOICES = (
        ('On', 'Online'),
        ('Off', 'Offline')
    )

    format = models.CharField(
        'Формат проведения',
        max_length=3,
        choices=FORMAT_CHOICES,
        default='On')
    city = models.ForeignKey(
        City,
        verbose_name='Город',
        on_delete=models.SET_NULL,
        related_name='courses',
        null=True,
        blank=True
    )

admin.py管理员.py

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ('name', 'category', 'format', 'city', 'date', 'date_add')
    list_filter = ('format' ,'date')
    search_fields = ('city', 'name', 'category')

    class Media:
        js = ('admin/js/hide_attribute.js',)

hide_attribute.js隐藏属性.js

document.addEventListener('DOMContentLoaded', function(){
  function toggleCity(value) {
    const cityWrapper = document.querySelector('.field-city');
    if (value === 'On') {
        cityWrapper.style.display = 'none';
    } else {
        cityWrapper.style.display = 'block';
    }
  }
  
  const formatSelect = document.querySelector('select#id_format');
  if (formatSelect) {
      toggleCity(formatSelect.value);
 
      formatSelect.addEventListener('click', function(){
          toggleCity(this.value);
      })    
  }

})

you can't use $('#id_content_type') to control inlines = (ContentInline,)你不能使用$('#id_content_type')来控制 inlines = (ContentInline,)

inlines has there own prefix, in your case, your first content inline will be like 'id_content-0-type'内联有自己的前缀,在您的情况下,您的第一个内联内容将类似于“id_content-0-type”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM