django管理员更改列表中的自定义list_editable字段,它不直接对应于模型字段 [英] Custom list_editable field in django admin change list, which doesn't correspond directly to a model field

查看:1970
本文介绍了django管理员更改列表中的自定义list_editable字段,它不直接对应于模型字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Assuming my model looks like this (this is a simplified example):

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

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

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

Displaying the name as a single column in the admin change list is easy enough. However, I need a single, editable "name" field that is editable from the list page, which I can then parse to extract and set the model field values. The parsing isn't a concern. I am just wondering how to have an editable form field on the list page that doesn't correspond directly to a model field.

推荐答案

您应该能够在纯Python中做一些工作。基本上,您需要使用 get_changelist_form 方法告诉它使用自定义窗体而不是默认的 ModelForm 为您的实例,然后初始化自定义字段的值正确(最方便地在窗体的 __ init __ 方法中),并专门为该表单的保存行为设置 first_name last_name 值。

You should be able to do this in pure Python with a bit of work. Basically, you need to use the get_changelist_form method on the admin class to tell it to use a custom form rather than a default ModelForm for your instances, then initialize the custom field's value properly (most conveniently in the form's __init__ method) and specialize the save behavior of that form to set the first_name and last_name values.

开始:

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

您还需要声明一个评估为 True list_editable $ c>当作为布尔值测试时 - 如果 list_editable 不使用 True

You will also need to declare a list_editable value that evaluates to True when tested as a boolean - some of the admin processing short-circuits without using the formset if list_editable does not evaluate as True.

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

If you have no other fields you want to be editable, this gets more complicated. The class validation requires that everything in the list_editable sequence be an editable field that's declared in list_display as well and is not a display link field. I think the options there are either to override the admin class's changelist_view method to use the full processing even if list_editable is not true, or to define a custom subclass of list or tuple that evaluates to True even when empty so it can pass validation. The former would require repeating a great deal of standard code and significantly increase your maintenance burden if you ever upgrade, while the latter is a counterintuitive hack and would not at all surprise me if it had unexpected consequences.

也不是很好的选择,所以我希望你至少有一个其他字段包含在 list_editable 中。

Neither are good options, so I hope you have at least one other field that makes sense to include in list_editable.

这篇关于django管理员更改列表中的自定义list_editable字段,它不直接对应于模型字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆