11

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

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

  def name():
    return first_name + ' ' + last_name

在管理员更改列表中将名称显示为单列很容易。但是,我需要一个可从列表页面编辑的单个可编辑“名称”字段,然后我可以对其进行解析以提取和设置模型字段值。解析不是问题。我只是想知道如何在列表页面上有一个不直接对应于模型字段的可编辑表单字段。

4

3 回答 3

35

你应该能够在纯 Python 中做一些工作。基本上,您需要使用get_changelist_form管理类上的方法来告诉它使用自定义表单而不是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
        return super(PersonChangeListForm, self).save(*args, **kwargs)

class PersonAdmin(admin.ModelAdmin):
    def get_changelist_form(self, request, **kwargs):
        return PersonChangeListForm

您还需要声明一个在测试为布尔list_editable值时评估为的值 - 如果不评估为 ,True则某些管理员处理短路而不使用表单集。list_editableTrue

如果您没有其他要编辑的字段,这将变得更加复杂。类验证要求list_editable序列中的所有内容都是在其中声明的可编辑字段,list_display而不是显示链接字段。我认为选项要么覆盖管理类的changelist_view方法以使用完整处理,即使list_editable不是真的,或者定义一个自定义子类listortuple评估为True即使是空的,这样它就可以通过验证。前者需要重复大量标准代码,如果升级的话,会显着增加维护负担,而后者是一种违反直觉的 hack,如果它产生意想不到的后果,我一点也不感到惊讶。

两者都不是好的选择,所以我希望您至少有一个其他领域可以包含在list_editable.

于 2013-10-11T03:29:53.347 回答
2

我只是在管理员中尝试了一个快速的问题模型。对于未在模型上定义的 list_editable 中的字段,管理员验证似乎失败。简而言之,您的问题的答案似乎是否定的。

但是,这并不意味着它不可行。使用一点 Javascript,您可以使用X-editable

(或自己滚动),并使“名称”列可编辑。创建一个视图来验证数据并将其保存到模型中。设置 X-editable 字段 'url' 参数以发布到此 URL。显然用 login_required / permissions_required 等装饰你的视图,以确保没有其他人可以编辑数据。

于 2013-10-07T20:16:44.853 回答
1

除了@Peter DeGlopper 答案:您可以在list_editable(例如last_name)中添加其他模型字段,然后覆盖change_list.html(查看此答案如何覆盖模板并在文件末尾添加一些 javascrip 代码: 模板/管理员/ your_app /person/change_list。 html :

{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_list %}
...

{% block content %}
...
{% endblock %}

{% block footer %}
{{ block.super }}
<script>
    var last_names = document.querySelectorAll('.field-last_name');

    last_names.forEach(function(el) {
        var input = el.children[0];
        var text = input.value;
        input.hidden = true;
        input.style.display = 'none';
        el.append(text);
    });
</script>
{% endblock %}
于 2017-05-12T12:06:32.937 回答