如何根据模型实例中的值有条件地更改django管理表单?

时间:2017-06-27 21:01:25

标签: python django django-forms django-admin models

所以我基本上想在没有设置另一个字段的情况下从django admin中删除一个字段。

例如,在这种情况下:

class Category(models.Model):
    name = models.CharField(max_length=30)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Topic(models.Model):
    name = models.CharField(max_length=30)
    category = models.ManyToManyField(Category)

class Document(models.Model):
    title = models.CharField(max_length=140)
    short_description = models.CharField(max_length=140)
    category = models.ManyToManyField(Category)
    topic = models.ManyToManyField(Topic, blank=True)
    def __str__(self):              # __unicode__ on Python 2
        return self.title

class DocumentsAdmin(admin.ModelAdmin):
    pass
admin.site.register(Document, DocumentsAdmin)

如果已经选择并保存了类别,我只想在管理员中显示主题表单字段。我这样做是因为应该可用的主题列表将是与已选择的类别相关联的主题的查询集。为了获取可能的主题选择,必须首先选择类别。

更新: 我修改了@alasdair在下面的评论中建议的解决方案,并制作了以下模型

class DocumentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(DocumentForm, self).__init__(*args, **kwargs)
        try:
            categories = self.instance.category.all()
            if categories:
                self.fields['topic'].queryset = Topic.objects.filter(category__in=categories)
            else:
                self.fields["topic"].widget = HiddenInput()
        except:
            self.fields["topic"].widget = HiddenInput()
    class Meta:
        model = Document
        fields = fields = [
            'title',
            'short_description',
            'category',
            'topic',
            ]

1 个答案:

答案 0 :(得分:1)

尝试定义模型表单,如果实例没有类别,则删除topic字段:

from django import forms

class DocumentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(DocumentForm, self).__init__(*args, **kwargs)
        if self.instance.pk:
            categories = self.instance.category.all()
        else:
            categories = None

        if categories:
            self.fields['topic'].queryset = self.fields['topic'].queryset.filter(category__in=categories)
        else:
            del self.fields['topic']

    class Meta:
        model = Document
        fields = [...]

然后使用模型管理类中的表单:

class DocumentsAdmin(admin.ModelAdmin):
    form = DocumentForm