【问题标题】:django admin "add page" initial datetime from GET parameters来自 GET 参数的 django 管理员“添加页面”初始日期时间
【发布时间】:2014-06-26 21:47:20
【问题描述】:

我想创建一个链接,该链接可以打开模型的 django 管理员添加页面,其中一些字段已预先填写。

我检查了是否可以将参数添加到添加表单的GET字典中,如:

<a href='/admin/myapp/mymodel/add?name=John'>add new mymodel with name John</a>

(实际上我用 {% url 'admin:myapp_mymodel_add' %} 得到了 url,但这只是为了明确)。

现在这适用于数值、文本值和外键。但是 DateTime 字段呢?当我尝试传递这样一个字段时(我尝试了许多格式,例如“2014-05-09 10:10:00”),我总是收到“服务器错误”的抱怨:

'unicode' 对象没有属性'date'

在代码行中:

django/forms/widgets.py 在解压中,第 902 行

 def decompress(self, value):
        if value:
            value = to_current_timezone(value)
            return [value.date(), value.time().replace(microsecond=0)] ...
        return [None, None]

变量“value”的值是我在 URL 上传递的值...

问题 1. 我认为服务器代码不应该根据用户传递的值引发异常...这不是 django 库中的错误吗?

问题 2。如何解决我的问题,即通过 GET 参数将初始日期时间传递给模型的管理“添加”页面?

【问题讨论】:

  • 你试过这种格式吗:2010-09-28+21:00:59?
  • 现在尝试:同样的错误...
  • 好的,如果您将日期和时间拆分为 2 个单独的参数会怎样:?date_field_name_0=2010-09-28&amp;date_field_name_1=21:00:59,其中date_field_name 是您的日期时间字段的名称?
  • @alecxe 这实际上是我尝试的第一件事(查看 POST 参数)。但是后缀为 _0 和 _1 的 GET 参数被简单地忽略(没有错误,但没有初始值)。
  • 你想通过GET参数设置什么日期时间字段?您能否展示包括DatetimeField 在内的模型定义?谢谢。

标签: django django-admin


【解决方案1】:

不,这不是错误;可能有人认为可以改进默认行为,但现有的实现是合理的第一遍(正如它适用于整数、字符串、外键等的事实所证明的那样)。有足够多的关于模型的元数据和足够的反序列化代码,可能可以在此处进行稍微更好的处理,但我不认为这是一个直接的错误。

好消息是有官方的方法来处理这个问题;在你的 ModelAdmin 类上,定义:

def get_changeform_initial_data(self, request):

此方法接受请求,并将该请求转换为将作为 initial 参数传递给更改列表(即管理中的添加或编辑页面)上的表单的值。如您所料,此方法的默认实现是“获取 GET 参数并转换为字典”;如果你对你知道是日期时间的字段做一些额外的处理,那么

或者,您根本不必使用请求对象。如果您知道“Person”对象的初始名称始终为“Unknown”,初始开始日期为 2014 年 1 月 1 日,那么您只需编写:

class PersonAdmin(ModelAdmin):
    ...
    def get_changeform_initial_data(self, request):
        return {
            'name': 'Unknown',
            'start_date': date(2014, 1, 1)
        }

即,不要关注请求数据,只需手动填充初始数据。由于它是表单的初始数据,因此对象上的任何现有数据都将覆盖initial 中提供的值,并且用户无需在GET 中提供任何参数即可使用该初始数据他们的要求。

【讨论】:

  • 谢谢!我看到这种方法可用于 django 1.7 不幸的是我目前使用的是 1.5。关于错误与否:每个基于具有日期字段的模型的管理界面都会受到此问题的影响。即使程序员不打算使用 GET 参数(并且可能没有意识到这种可能性),管理界面也会公开它们并为每个管理员用户提供生成服务器错误的可能性。在 1.7 版之前,这也很难修复(我认为需要重新定义 ModelAdmin.changeform_view)。
  • 无论如何,这只是一个学术讨论,因为我同意管理界面应该由选定的用户使用,这些用户在访问和修改数据库方面已经拥有更多“危险”权限。但是,我认为管理应用程序的“正确”默认行为应该是向用户写入错误消息,就好像该值是使用 POST 参数插入的一样,或者可能引发 InvalidRequest 而不是 ServerError。
【解决方案2】:

看来问题是您在需要日期时传递了一个字符串。您需要先将字符串转换为日期。

可以使用内置的python库datetime:

 import datetime
 value = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
 def decompress(self, value):
     ...

编辑:alecxe 正确地指出我没有正确回答您的问题。经过一番搜索,我发现了一些可能更相关的东西。

根据answer,Django 允许您在处理 GET 字典之前替换它。借用这个例子,我们可以截取你的get参数并将字符串日期替换为GET字典中的datetime对象,这似乎是可行的

    def add_view(self, request, form_url='', extra_context=None):
        // any extra processing can go here...
        g = request.GET.copy()
        g.update({
            'date':datetime.datetime.strptime(request.GET.get('date'), "%Y-%m-%d %H:%M:%S"),
        })

        request.GET = g
        return super(MyModelAdmin, self).add_view(request, form_url, extra_context)

【讨论】:

  • 与问题中描述的问题无关。
  • 我不同意。 Emanuele Paolini 报告收到的错误消息是“'unicode' object has no attribute 'date'”。这是由于尝试在 unicode 对象上调用 .date() 引起的。
  • 我不是在争论这个。问题是不是他自己写的代码。它是 django 源代码库的一部分。这要么是一个应该报告的错误,要么应该有一种方法(或解决方法)让它工作。
猜你喜欢
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多