如何在显示表单之前在自动生成的表单中设置字段的初始值以添加Django模型实例?我正在使用Django 1.3.1。
我的模型如下:
class Foo(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
并且当前的管理表单确实没什么特别的
class FooAdmin(admin.ModelAdmin):
ordering = ('title',)
当我使用管理页面添加一个新的Foo实例时,我得到一个很好的表单,其中包含标题和描述的空字段。我想要的是描述字段是通过调用函数获得的模板设置的。
我目前最好的尝试是:
def get_default_content():
return 'this is a template for a Foo description'
class FooAdminForm(django.forms.ModelForm):
class Meta:
model = Foo
def __init__(self, *args, **kwargs):
kwargs['initial'].update({'description': get_default_content()})
super(FooAdminForm, self).__init__(self, *args, **kwargs)
class FooAdmin(admin.ModelAdmin):
ordering = ('title',)
form = FooAdminForm
但如果我试试这个,我会收到这个Django错误:
AttributeError at /admin/bar/foo/add/
'FooForm' object has no attribute 'get'
Request Method: GET
Request URL: http://localhost:8000/admin/bar/foo/add/
Django Version: 1.3.1
Exception Type: AttributeError
Exception Value: 'FooForm' object has no attribute 'get'
Exception Location: /www/django-site/venv/lib/python2.6/site-packages/django/forms/widgets.py in value_from_datadict, line 178
我不知道这里有什么问题,我应该做些什么才能让它发挥作用。我也觉得这个错误很奇怪(除了我完全看到它的事实)是我的代码中根本没有FooForm?
答案 0 :(得分:23)
Alasdair的方法很不错但过时了。 Radev的方法看起来很不错,正如评论中所提到的那样,令我印象深刻的是文档中没有任何内容。
除此之外,由于Django 1.7在ModelAdmin中有一个函数get_changeform_initial_data
,它设置初始表单值:
def get_changeform_initial_data(self, request):
return {'name': 'custom_initial_value'}
答案 1 :(得分:21)
您需要在self
方法定义中包含__init__
作为第一个参数,但在调用超类方法时不应包含它。
def __init__(self, *args, **kwargs):
# We can't assume that kwargs['initial'] exists!
if 'initial' not in kwargs:
kwargs['initial'] = {}
kwargs['initial'].update({'description': get_default_content()})
super(FooAdminForm, self).__init__(*args, **kwargs)
话虽如此,模型字段可以对其default进行调用,因此您可能根本不需要定义自定义管理表单。
class Foo(models.Model):
title = models.CharField(max_length=50)
description = models.TextField(default=get_default_content)
答案 2 :(得分:9)
超过3年后, 但实际上你应该做的是覆盖admin.ModelAdmin formfield_for_dbfield ..就像这样:
class FooAdmin(admin.ModelAdmin):
def formfield_for_dbfield(self, db_field, **kwargs):
field = super(FooAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'description':
field.initial = 'My initial description'
elif db_field.name == 'counter':
field.initial = get_counter() + 1
return field
干杯;
答案 3 :(得分:0)
添加新对象时,按照get_changeform_initial_data()的建议使用Wtower很方便。
但是,当更改现有对象时,这不起作用(请参阅source)。
在这种情况下,您可以按如下方式扩展 ModelAdmin.get_form()(使用 OP 的示例):
def get_form(self, request, obj=None, change=False, **kwargs):
if obj and not obj.description:
obj.description = get_default_content()
return super().get_form(request, obj, change, **kwargs)