【问题标题】:How to set initial data for Django admin model add instance form?如何为 Django 管理模型添加实例表单设置初始数据?
【发布时间】:2012-04-17 13:27:33
【问题描述】:

如何在自动生成的表单中设置字段的初始值,以便在显示表单之前添加 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?

【问题讨论】:

    标签: django forms model admin


    【解决方案1】:

    Alasdair 的方法很好,但已经过时了。 Radev 的方法看起来相当不错,正如评论中所提到的,让我感到震惊的是,文档中没有任何关于此的内容。

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

    def get_changeform_initial_data(self, request):
        return {'name': 'custom_initial_value'}
    

    【讨论】:

    • 出于某种原因在 1.10.2 中根本没有调用此方法,尽管它存在于文档中
    • @scythargon 我刚刚在 1.10.2 中对其进行了测试,对我来说它按记录工作。
    • 很容易忘记 ModelAdmin 的所有可用挂钩。谢谢!
    • 面对同样的方法没有被调用的问题,我深入研究了源代码。答案很简单,它只对新创建的对象调用。更改现有对象将不会调用它。
    • 内联有类似的功能吗?
    【解决方案2】:

    您需要在__init__ 方法定义中包含self 作为第一个参数,但在调用超类的方法时不应包含它。

    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)
    

    【讨论】:

    • 哇,这就像一个魅力!顺便说一句,对于这样一个愚蠢的错误,这是一个非常神秘的消息......非常感谢您的帮助!
    • 对了,你的第二个建议我也试过了,更干净了,再次感谢!
    • 我发现设置 kwargs['initial'] 导致保存表单时出错。我设置了一个 if 子句: if 'initial' in kwargs.keys(): kwargs['initial'].update(... 这用于显示初始值并更新它们。
    • @Sven 好点。如果kwargs 中不存在,我已更新我的答案,将initial 设置为空字典。
    【解决方案3】:

    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
    

    干杯;

    【讨论】:

    • 非常好。这很奇怪,但文档中没有这样的东西:docs.djangoproject.com/en/1.8/ref/contrib/admin
    • 不幸的是,Django 管理员的“方式”记录不足。
    • 或者您可以删除field = super... 行,设置kwargs['initial'] = 'My initial description''counter' 字段类似),然后是return super...,这样可以节省一行。
    【解决方案4】:

    在添加new对象时,按照Wtower的建议使用get_changeform_initial_data()比较方便。

    但是,当更改 现有 对象时,这不起作用(请参阅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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 2015-10-25
      • 2014-01-04
      • 1970-01-01
      • 2014-08-22
      • 2018-05-06
      • 2010-12-02
      相关资源
      最近更新 更多