django管理员更改列表中的自定义list_editable字段,它不直接对应于模型字段

Ben*_*rts 9 python django django-admin

假设我的模型看起来像这样(这是一个简化的例子):

class Person(Model):
  first_name = CharField(...)
  last_name = CharField(...)

  def name():
    return first_name + ' ' + last_name
Run Code Online (Sandbox Code Playgroud)

在管理更改列表中将名称显示为单个列非常简单.但是,我需要一个可编辑的"名称"字段,该字段可从列表页面进行编辑,然后我可以解析该字段以提取和设置模型字段值.解析不是问题.我只是想知道如何在列表页面上创建一个不直接与模型字段对应的可编辑表单字段.

Pet*_*per 26

你应该能够在纯Python中做一些工作.基本上,您需要使用get_changelist_formadmin类中的方法告诉它使用自定义表单而不是ModelForm实例的默认值,然后正确初始化自定义字段的值(最方便地在表单的__init__方法中)并专门save化该表单的行为设置first_namelast_name值.

这样的事情应该是一个开始:

class PersonChangeListForm(forms.ModelForm):
    class Meta:
        model = Person
    name = forms.CharField()

    def __init__(self, *args, **kwargs):
        instance = kwargs.get('instance')
        if instance:
            initial = kwargs.get('initial', {})
            initial['name'] = '%s %s' % (instance.first_name, instance.last_name)
            kwargs['initial'] = initial
        super(PersonChangeListForm, self).__init__(*args, **kwargs)

    def save(self, *args, **kwargs):
        # use whatever parsing you like here
        first_name, last_name = self.cleaned_data['name'].split(None, 1)
        self.cleaned_data['first_name'] = first_name
        self.cleaned_data['last_name'] = last_name
        super(PersonChangeListForm, self).save(*args, **kwargs)

class PersonAdmin(admin.ModelAdmin):
    def get_changelist_form(self, request, **kwargs):
        return PersonChangeListForm
Run Code Online (Sandbox Code Playgroud)

您还需要声明一个list_editable值,该值True在测试时作为布尔值进行测试 - 一些管理处理短路而不使用formset,如果list_editable不评估为True.

如果您没有其他字段可以编辑,则会变得更加复杂.类验证要求list_editable序列中的所有内容都是可以在其中声明的可编辑字段,list_display而不是显示链接字段.我认为有两种选项覆盖管理类的changelist_view使用完整的处理,即使方法list_editable是不正确的,或者自定义一个子类,listtuple计算结果为True即使空当,因此它可以通过验证.前者需要重复大量的标准代码,并且如果你升级会显着增加你的维护负担,而后者是一个违反直觉的黑客,如果它有意想不到的后果,我一点都不会感到惊讶.

这两个都不是很好的选择,所以我希望你至少有一个其他有意义的领域list_editable.

  • 这肯定让我走在正确的轨道上...我必须在list_editable字段中使用一个实际的模型字段列(即'first_name'),只是将显示名称更改为"全名",然后使用__init__和save方法实际解析值并保存它们.据我所知,我无法将非模型表单字段显示为列表页面中的列.但它成功了.谢谢! (2认同)