Django - 自定义模型方法 - 如何指定数据类型,以便管理员正确格式化?

时间:2011-04-11 13:03:38

标签: django django-models django-admin

示例:

class MyModel(models.Model):
    field1=models.CharField(..)
    field2=models.DateTimeField()
    def today(self):
        return self.field2

当我在管理网站中查看此内容时,field2的格式与今天字段的格式不同。

我怎样才能告诉管理网站今天如何对待field2?即,告诉Django管理员'今天'是模特.DateTimeField?

以下是它的内容:

Field2                  today
April 5, 2011, 9:10 a.m.    2011-04-11 08:47:27

4 个答案:

答案 0 :(得分:2)

获取DateTime对象来电datetime.datetime.now()而不是datetime.datetime.today()

编辑:

或者使用models.DateField()代替field2代替models.DateTimeField(): - )

EDIT2:

以下是解决方案:

def today(self):
    from django.utils import formats
    return formats.localize(self.field2)

答案 1 :(得分:1)

这是一些非常奇怪的行为。总计 guess ,它可能与django设置有关;特别是DATETIME_FORMAT(及相关)设置。框架可能对字段进行内省,如果它们是DateTime类型,则根据上述设置进行渲染。

在大多数情况下对方法的反省是没有意义的,所以如果是这样的话,我就能理解这种行为。

尝试相应地修改设置(提供不同的日期时间格式),并查看字段是否更改以及方法是否保持不变。

编辑:

查看django.contrib.databrowse.datastructures,有一段代码可以执行以下操作:

if isinstance(self.field, models.DateTimeField):
    objs = capfirst(formats.date_format(self.raw_value, 'DATETIME_FORMAT'))

我想在管理员应用程序中发生了类似的事情,但我目前找不到确切的参考。

要实现您的目标,您需要适当地设置日期时间格式:

def today(self):
    from django.conf import settings
    return self.field2.strftime(settings.DATETIME_FORMAT)

或者,使用@ cata的评论:

def today(self):
    from django.utils.formats import localize
    return localize(self.field2)

答案 2 :(得分:1)

如果您选择通过自己的功能提供“list_display”项目,并且您对默认输出不满意,则需要自行格式化。在这种情况下,如果您希望具有与DateTime数据库字段最终结果相同的格式:

from django.utils import formats
def today(self):
        return formats.localize(self.field2)

背景:

templates/admin/change_list.html

使用模板标记

django.contrib.admin.templatetags.admin_list.result_list

反过来会调用

django.contrib.admin.templatetags.admin_list.items_for_result()

为每行渲染单个列值。

你会看到你的两个值都开始成为一个DateTime实例,无论是通过数据库查找还是调用你的函数,参见

django.contrib.admin.util.lookup_field()

但是如果有数据库字段,返回值“f”将只是一个字段。您提供了一个函数,因此lookup_field()仅提供值,“f”将为None。

因此在items_for_result()中,您的值将通过“if f is None”块运行并错过

result_repr = display_for_field(value, f)

换句话说,

django.contrib.admin.util.display_for_field()

只会根据字段类型调用数据库值进行格式化,因此这是您的函数值缺失的处理方法:

elif isinstance(field, models.DateField) or isinstance(field, models.TimeField):
    return formats.localize(value)

如上所示,您需要自己完成最后一行。

编辑:关于你的问题

  

如何告诉管理网站要处理   今天喜欢它治疗field2?即,   告诉Django管理员'今天'是一个   models.DateTimeField?

它不是models.DateTimeField,它是一个函数值。如果它是models.DateTimeField,它将描述您的模型。看看所有需要的东西:http://docs.djangoproject.com/en/dev/ref/models/fields/ 在您的示例中,您真的可以使用field2。显然你想要做它的价值,计算它等等 - 那么今天是什么呢?那么呢?

也就是说,如果函数值是DateTime实例默认情况下通过format.localize()运行会很好,因为这就是本地化的文档似乎很有希望。 顺便说一下,我宁愿在ModelAdmin中定义一个格式化的值,而不是模型本身。我通常把它称为“formatted_today”(保持原来今天()的日期时间值),只是如果管理员是唯一需要格式化值的地方,imho就是应该定义的地方。

答案 3 :(得分:0)

之前的所有答案都提供了解决方案,可以在新的Django版本中错误地处理时区信息。

如果field2

todaysettings.USE_TZ==True通常会显示不同的时间。

我今天发现了这个问题,并花了一些时间来找出正确的方法:

from django.db import models
from django.contrib import admin
from django.utils.timezone import template_localtime
from django.utils.formats import localize


class MyModel(models.Model):
    # ...
    field2=models.DateTimeField()

class MyModelAdmin(admin.ModelAdmin):
    # ...
    def today(self, obj):
        return localize(template_localtime(obj.field2))

admin.site.register(MyModel, MyModelAdmin)