管理员中的Django / jQuery级联选择框

时间:2015-02-16 11:31:49

标签: javascript jquery ajax django django-admin

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

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

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-choices或django-ajax-select

1 个答案:

答案 0 :(得分:0)

在类似的情况下,我做了以下(现在适合您的模型):

模型

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,只会隐藏下拉列表。