在Django中显示模型对象的datetime属性的本地时间

时间:2017-09-13 17:16:34

标签: python django datetime django-tables2

我正在努力使模型对象的datetime字段属性在模板中显示为当前用户的时区的本地时间。我的设置中的默认时区是UTC。这是一个示例模型:

models.py

class Basic(models.Model):
    name = models.CharField(max_length=128)
    created_at = models.DateTimeField(auto_now_add=True

我想要显示的数据位于使用django-tables2制作的表格中。但是,我已经尝试了两种方法,但它们都不起作用:

tables.py尝试1:

class ShipperDataFileDocumentTable(tables.Table):
    created_at = tables.TemplateColumn('''
                                        {% load tz %}
                                        {% localtime on %}
                                            {{ record.created_at }}
                                        {% endlocaltime %}
                                      ''')
    class Meta:
        model = Basic
        fields = ('name', 'created_at')

tables.py尝试2:

class ShipperDataFileDocumentTable(tables.Table):
    created_at = tables.TemplateColumn('''
                                        {% load tz %}
                                        {{ record.created_at|localtime }}
                                      ''')
    class Meta:
        model = Basic
        fields = ('name', 'created_at')

这两种方法最终都没有改变时间。例如,我在美国东部时间中午12:00制作了一个物体。通常,模板会将其显示为UTC的下午4:00。但是,即使进行了这些编辑,它仍然显示时间为下午4:00。我不确定我做错了什么。

编辑:有没有办法检测用户的当前时区?我已经尝试过django-easy-timezones,但由于某些原因无效。

2 个答案:

答案 0 :(得分:0)

Django为handle this提供了一种方式:

  1. 启用时区支持:

    在设置文件中设置UZE_TZ = True

  2. 然后实现选择用户时区的方法:

    An example with a form and a middleware。   但是IMO的更简单(比显式形式)解决方案是detect it in js,然后将其放在用户会话/ cookie中。   例如,使用moment.js:

    Session['tz'] = moment.tz.guess()

  3. 然后在模板中渲染localtime

  4. 或者,如果您不想处理服务器端并且更喜欢在客户端执行,则django将时区设置为iso 8601中的template,然后convert it in js或{ {3}}

    很多解决方案,但仍然是jQuery ......

答案 1 :(得分:0)

另一个回答不好的问题需要我的帮助。使用JavaScript来转换时间将是一种有效的方法,但由于其复杂性,我建议使用像moment.js这样的库。然而,有一种比学习新的JS框架更简单的方法。 django-tables2认为你想要GMT中的datetime对象,但你可以告诉它使用local作为显示。如果您阅读python文档,UZE_TZ = True对于生产等级代码来说是一个坏主意,因为您的日期时间将存储为本地时间,使得跨时区的同步几乎不可能。你想要的是一个可以识别时区的日期时间对象,比如2018-03-07 08:34:32.212841-05。您的代码created_at = models.DateTimeField(auto_now_add=True)只创建了这样一个对象,因此第一步正确完成。第二步,在当地时间向用户显示时间。将其添加到您的模型中(我对东方进行了硬编码演示,如果您阅读了pytz文档,那么还有一个本地化函数):

def localTimeCreated(self): return self.created_at.astimezone(pytz.timezone('US/Eastern')).strftime("%H:%M:%S %p")

现在我们需要排除旧created_at并引用新方法。转到您的表类,添加此属性,然后更改Meta:

createdFormatted = tables.Column(accessor='localTimeCreated', verbose_name='Created') # verbose_name = column header

class Meta:
    model = Basic
    fields = ('name', 'createdFormatted')
    exclude = ('created_at')
    sequence = ('createdFormatted', 'name' ) #default: extra columns at the end
    attrs = {"class" : "table-striped table-bordered"}
    empty_text = "User not found."

最后两个属性不相关,但对专业外观有好处。