我有一个模型Foo
,它有几个数据库属性和几个基于组合因素计算的属性。我想把这些计算属性呈现给用户,就好像它们是数据库属性一样(后台因素将根据用户输入而更改)。在Django管理界面中是否有实现此功能的方法?
我有一个模型Foo
,它有几个数据库属性和几个基于组合因素计算的属性。我想把这些计算属性呈现给用户,就好像它们是数据库属性一样(后台因素将根据用户输入而更改)。在Django管理界面中是否有实现此功能的方法?
我建议您为Foo
创建一个模型表单的子类(FooAdminForm),以添加自己的不由数据库支持的字段。您的自定义验证可以在ModelForm的clean_*
方法中完成。
在FooAdmin
的save_model
方法中,您可以获取请求(request)、Foo
实例和表单数据,因此您可以在保存实例之前/之后处理所有数据。
这是一个在Django管理界面注册了自定义表单的模型的示例:
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)
BooleanField
(它默认使用CheckboxInput
小部件)。在Django中,表单字段接受initial
关键字参数,例如:bar = forms.BooleanField(initial=True)
。 - Reiner Gereckesuper(FooAdminForm, self).__init_(...)
而不是ModelForm.__init__(self,...)
。两者都可以,但是super
更受欢迎。 - brianmearnsbase_fields
。那是一个类属性!相反,首先调用 __init__
(并请使用 super
),然后使用 self.fields
。 - DylanYoungsave
,只需使用commit=False
调用super
(这将返回未保存的对象),根据需要修改您的模型,对对象调用save
,然后在表单上调用self.save_m2m()
。 - DylanYounglist_display
随意接受实际模型属性或在模型或模型管理器上定义的方法,您可以子类化 forms.ModelForm
以向更改表单添加任何字段类型。list_editable
进行原地编辑的任意数据。 Django 似乎只接受与数据库字段相对应的真实模型属性。(即使在模型定义中使用 @property
方法也不够)。您可以在模型中使用@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')
@property
不是必需的。list_display
将接受模型(或 ModelAdmin)上的任何方法。 - Chris Pratt