如何为Django管理模型添加实例表单设置初始数据?

Mar*_*ano 19 forms django model admin

在显示表单之前,如何在自动生成的表单中设置字段的初始值以添加Django模型实例?我正在使用Django 1.3.1.

我的模型如下:

class Foo(models.Model):
  title = models.CharField(max_length=50)
  description = models.TextField()
Run Code Online (Sandbox Code Playgroud)

而目前的管理形式真的没什么特别的

class FooAdmin(admin.ModelAdmin):
  ordering = ('title',)
Run Code Online (Sandbox Code Playgroud)

当我使用管理页面添加一个新的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
Run Code Online (Sandbox Code Playgroud)

但如果我尝试这个,我得到这个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
Run Code Online (Sandbox Code Playgroud)

我不知道这里有什么问题,我应该做些什么才能让它发挥作用.我也觉得这个错误很奇怪(除了我完全看到它的事实)是我的代码中根本没有FooForm?

Wto*_*wer 24

Alasdair的方法很好但过时了.Radev的方法看起来很不错,正如评论中所提到的那样,令我印象深刻的是文档中没有任何相关内容.

除此之外,由于Django 1.7 get_changeform_initial_data在ModelAdmin中有一个设置初始表单值的函数:

def get_changeform_initial_data(self, request):
    return {'name': 'custom_initial_value'}
Run Code Online (Sandbox Code Playgroud)

  • 很容易忘记 ModelAdmin 的所有可用挂钩。谢谢你! (2认同)
  • 面对未调用方法的同一问题,我深入了源代码。答案很简单,仅针对新创建的对象。更改现有对象将“不”调用它。 (2认同)

Ala*_*air 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)
Run Code Online (Sandbox Code Playgroud)

话虽如此,模型字段可以将其默认值设置为可调用,因此您可能根本不必定义自定义管理表单.

class Foo(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField(default=get_default_content)
Run Code Online (Sandbox Code Playgroud)


Ram*_*raf 10

超过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
Run Code Online (Sandbox Code Playgroud)

干杯;