Django:在管理界面中伪造一个字段?

问题描述 投票:0回答:4

我有一个模型,

Foo
。它具有多个数据库属性以及多个基于因素组合计算的属性。我想将这些计算属性呈现给用户,就好像它们是数据库属性一样。 (支持因素将发生变化以反映用户输入。)有没有办法使用 Django 管理界面来做到这一点?

python django django-admin
4个回答
35
投票

我建议您对

Foo
(FooAdminForm) 的模型表单进行子类化,以添加您自己的不受数据库支持的字段。您的自定义验证可以驻留在 ModelForm 的
clean_*
方法中。

save_model
FooAdmin
方法中,您可以获得请求、
Foo
的实例和表单数据,因此您可以在保存实例之前/之后对数据进行所有处理。

这是一个使用 django admin 注册的自定义表单的模型示例:

from django import forms
from django.db import models
from django.contrib import admin


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


class FooAdminForm(forms.ModelForm):
    # custom field not backed by database
    calculated = forms.IntegerField()

    class Meta:
        model = Foo 


class FooAdmin(admin.ModelAdmin):
    # use the custom form instead of a generic modelform
    form = FooAdminForm

    # your own processing
    def save_model(self, request, obj, form, change):
        # for example:
        obj.name = 'Foo #%d' % form.cleaned_data['calculated'] 
        obj.save()


admin.site.register(Foo, FooAdmin)

根据实例数据为自定义字段提供初始值

(我不确定这是否是最好的解决方案,但它应该有效。)

当构建数据库中现有模型实例的模型表单时,它会传递该实例。因此,在 FooAdminForm 的

__init__
中,可以根据实例数据更改字段属性。

    def __init__(self, *args, **kwargs):
        super(FooAdminForm, self).__init__(*args, **kwargs)
        # only change attributes if an instance is passed            
        instance = kwargs.get('instance')
        if instance:
            self.fields['calculated'].initial = (instance.bar == 42)

7
投票

获取任意数据显示在更改列表中或使字段显示在表单中非常容易:

list_display
任意采用实际模型属性,或者模型或模型管理上定义的方法,并且您可以子类
forms.ModelForm 
将您想要的任何字段类型添加到更改表单中。

更困难/不可能的是将两者结合起来,即在更改列表中包含任意数据,您可以通过指定

list_editable
就地编辑。 Django 似乎只接受与数据库字段相对应的真实模型属性。 (即使在模型定义中的方法上使用
@property
也是不够的)。

有没有人找到一种方法可以直接从更改列表页面编辑模型上实际不存在的字段?


2
投票

您可以在模型中使用

@property
装饰器(Python >= 2.4):

class Product(models.Model):

    @property
    def ranking(self):
        return 1

ranking
然后可以在
list_display
:

中使用
class ProductAdmin(admin.ModelAdmin):
    list_display = ('ranking', 'asin', 'title')

1
投票

在编辑表单中,将属性名称放入readonly_fields(仅限1.2以上)。

在变更列表中,将其放入list_display

© www.soinside.com 2019 - 2024. All rights reserved.