【问题标题】:Django/jQuery Cascading Select Boxes in Admin管理中的 Django/jQuery 级联选择框
【发布时间】:2015-04-16 21:48:01
【问题描述】:

我有一个合同类,其中 contract_mod 允许从以前的合同扩展合同。 contract_mod 应该只显示与我们之前选择的人相关的合同。 Contract 类返回字段person。因为我从来没有使用过 AJAX/jQuery,所以我不知道从哪里开始。

所以,我的目标是字段 contract_mod 取决于 hte 字段 person(使用管理界面)。

class Contract(models.Model):
    person        = models.ForeignKey(Person) #person hired
    contract_mod  = models.OneToOneField('self', blank = True, null = True) #allows to extend a contract
        ...

由于字段 contract_mod 是 OneToOneField 我不能使用 django-smart-selects 或 django-ajax-select

【问题讨论】:

    标签: javascript jquery ajax django django-admin


    【解决方案1】:

    在类似的情况下,我做了以下事情(现在适应了你的模型):

    型号

    class Person(models.Model):
        name = models.CharField(max_length=20)
        def __unicode__(self):
            return self.name
        def get_name(self):
            return self.name
    
    class Contract(models.Model):
        person        = models.ForeignKey(Person) #person hired
        contract_mod  = models.OneToOneField('self', blank = True, null = True)
        contract_name = models.CharField(max_length=20) #just for testing
    
        def __unicode__(self):
            return self.get_name() + " " +self.contract_name
        def get_name(self):
            return self.person.get_name() #to make sure you get the person name in the admin
        def contract_mod_name(self):
            if self.contract_mod:
                return self.contract_mod.contract_name
            else:
                return ""
    

    管理员

    class SelectField(forms.ChoiceField):
        def clean(self, value):
            return value
    
    class CForm(forms.ModelForm):
        contracts_from_selected = SelectField()
        class Meta:
            model = Contract
            widgets = { 'contract_mod' : forms.widgets.Select(attrs={'hidden' : 'true'}) }
    
    class CAdmin(admin.ModelAdmin):
        form = CForm
        list_display = ('contract_name','get_name','contract_mod_name')#what you like
        def save_model(self, request, obj, form, change):
            if request.POST.get('contracts_from_selected'):
                obj.contract_mod=Contract.objects.get(id=int(request.POST.get('contracts_from_selected')))
    
            obj.save()
    

    覆盖 change_form.html 模板(通过将其从 django/contrib/admin/templates/admin 复制到 yourapp/templates/admin/yourapp 目录中)并添加以下 Javascript:

    $(function () {
        $("#id_person").change(function () {    
            var options = $("#id_contract_mod option").filter(function () {
                return $(this).html().split(" ")[0] === $("#id_person   option:selected").html();
            }).clone();
            $("#id_contracts_from_selected").empty();
            $("#id_contracts_from_selected").append(options);
        });
    });
    

    一个缺点是,它使用可见的 html 条目来存储人-合同关系。所以这个人在下拉列表中也是可见的。为避免这种情况,您可以向选项添加一个属性 - 请参见此处: Django form field choices, adding an attribute

    是的,最好完全隐藏contract_mod ChoiceField。通过小部件中的 hidden=True 仅隐藏下拉菜单。

    【讨论】:

    • 它没有显示任何错误但还没有工作。当我使用 Grappelli 时,我从它的 directory 中获取 change_form 并在 Javascript 的一部分中添加该函数(我应该把它放在其他地方吗?)无论如何,很高兴知道我并不孤单 :)
    • 如果我不隐藏小部件,我可以看到它是空的。 @ger.s.brett
    • 如果为空,Javascript 可能不起作用。您能否检查浏览器是否找到了 Javascript(例如使用 Firebug 或取决于您使用的浏览器)?我还没有和 Grapelli 合作过(还)。我把它放在模板的底部,就在最后的 {% endblock %} 语句之前。
    • 它有效,但在字段contracts_from_selected中显示名称而不是在contract_mod中
    • 是的,这就是它背后的想法。有效的选择选项被加载到contracts_from_selected 表单域中。
    猜你喜欢
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    相关资源
    最近更新 更多