Custom list_editable field in django admin change list, which doesn't correspond directly to a model field

后端 未结 3 612
攒了一身酷
攒了一身酷 2020-12-31 15:38

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

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

  def nam         


        
3条回答
  •  孤城傲影
    2020-12-31 15:58

    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.

    Something like this should be a start:

    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
    

    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.

    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.

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

提交回复
热议问题