【问题标题】:How to convert Django's TimeField to Postgres' timestamp with time zone如何将 Django 的 TimeField 转换为 Postgres 的带时区时间戳
【发布时间】:2015-10-07 20:10:38
【问题描述】:

在我的 Django 应用程序中,程序从用户那里获取事件的时间,比如用户输入 10:30 作为事件的时间。该程序使用 modelformset_factory 来创建一大堆表单:

#forms.py
class EventForm(ModelForm):
    class Meta:
        model = Event
        fields = ['entry', 'time', 'work']
        localized_fields = ('time', )
        widgets = {
        'work': Textarea(attrs = {'cols': 40, 'rows': 8}),
        }

#models.py
class Event(models.Model):
    '''
    Each day there are many events, e.g. at 10 am, the framer orders material, etc.
    '''
    entry = models.ForeignKey(Entry)
    time = models.TimeField()
    work = models.TextField()


#views.py:

EventFormSet = modelformset_factory( Event, form = EventForm, exclude = ('entry',),extra = 5)

eventset = self.EventFormSet(request.POST)

all_errors = eventset.errors # All errors returns [{}, {}, {}, {}, {}], so the data is free of error.
try:
    eventset.is_valid()             
except ValidationError:
    return render(request, self.template_name, {'form': self.day_log(initial = self.initial_values), 'eventforms': self.event_formset})
events_instances = eventset.save(commit = False)

for instance in events_instances:
    if instance.time:
        event_date = datetime.date(the_year, the_month, the_day) # Naive date
        event_time = instance.time # Naive time
        naive_event_time = timezone.is_naive(event_time) # Checking naivaty 
        event_datetime = datetime.datetime.combine(event_date, event_time) # Naive datetime object
        is_aware_event_datetime = timezone.is_aware(event_datetime) # Checking to see if the datetime object is aware or naive
        event_aware_datetime = datetime.datetime(the_year, the_month, the_day, instance.time.hour, instance.time.minute, instance.time.second, tzinfo = pytz.utc) # Making an aware time
        is_aware_event_aware_datetime = timezone.is_aware(event_aware_datetime) # Making sure the event_aware_datetime is indeed aware
        instance.time = event_aware_datetime
        awareness_test = timezone.is_aware(instance.time) # Making sure instance.time is aware
        eventset.save()  # Here is where the exception is thrown.

Django 应用无法将时间数据保存到 Postgres。异常类型为 DataError,异常值为:

invalid input syntax for type timestamp with time zone: 
LINE 1: ...y_event" ("entry_id", "time", "work") VALUES (14, '18:43:04....

用 ^ 指向 ' of '18:

编辑: 这是我的数据库:

CREATE TABLE site_activity_event
(
    id serial NOT NULL,
    entry_id integer NOT NULL,
    "time" time without time zone NOT NULL,
     work text NOT NULL,
     CONSTRAINT site_activity_event_pkey PRIMARY KEY (id),
     CONSTRAINT site_activity_event_entry_id_fkey FOREIGN KEY (entry_id)
        REFERENCES site_activity_entry (id) MATCH SIMPLE
        ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED
    )

我对我的应用程序进行了 sqlall,以确保模型字段的数据类型与应用程序的数据类型相对应,并且一切正常。这似乎是一个 postgres 问题,但 Django 应该处理 Postgres (https://docs.djangoproject.com/en/1.8/topics/i18n/timezones/#migration-guide) 的所有那些讨厌的界面问题,所以这让我觉得我错过了一些东西。非常感谢任何帮助。

【问题讨论】:

  • 显示你的request.POST

标签: python django postgresql django-models timestamp


【解决方案1】:

那么,“18:43:04”是带时区的有效时间戳吗?你认为它指定了一个独特的时间点吗?如果你这样做了,那么你就发现了 PostgreSQL 日期/时间处理中的一个主要错误。如果没有,那么您应该提供一个有效的时间戳或在您的数据库中使用正确的类型 - 如果不了解这些事件的更多信息,我不能说哪个。

【讨论】:

  • 问题是当用户输入 09:00 时,Django 应该以 Postgres 可以接受的格式将其提供给 Postgres。它显然没有。我什至尝试为我的模型表单集的每个实例手动创建一个类似格式的对象,但是在添加时区时会变得很乱。
  • 我认为您的意思是需要明确提及时区以避免歧义。问题是当用户输入 09:00 时,Django 应该以 Postgres 可以接受的格式将其提供给 Postgres。它显然没有。现在,我三个小时的研究表明,这可能与我没有 pytz 设置有关。所以,我这样做了:event_awaretime = pytz.timezone("Canada/Pacific").localize(event_datetime, is_dst = None) 然后对于我的表单集的每个实例,我都这样做了:instance.time = event_awaretime。我得到了同样的错误!应该有更简单的方法。
  • 仍然不是时间戳。您是否查看过 PostgreSQL 文档以了解时间戳实际上是什么
  • 好的,问题是如何将简单的 9:10 输入转换为可接受的 Postgres 输入。我知道天真的时间应该转换为感知时间,并且 tzinfo 也应该包括在内:event_aware_datetime = pytz.timezone("Canada/Pacific").localize(event_datetime, is_dst = None)。但是,问题是即使这对 Postgres 来说也是不可接受的。我希望你能详细解释如何做到这一点。我是初学者,经过数小时的阅读后,我来这里询问其他专家。
  • "9:10" 甚至不是一个时间 - 它可能是早上或晚上。在没有日期的情况下添加区域时区(例如“欧洲/伦敦”)是没有意义的。时间戳代表一个时间点,例如“2015 年 7 月 23 日星期四 23:31:47 BST”。所以 - 您想要数据库中的“时间”或应用程序中的“时间戳”。这实际上与数据库甚至计算无关。这是对单位的基本了解。
【解决方案2】:

您的活动有一个 TimeField,但看起来数据库是使用 DateTimeField 创建的。

【讨论】:

  • 我编辑了我的帖子以显示数据库 sql。请详细说明
  • @EarlyCoder - 这是 Django 的 sql 输出吗?尝试查看创建的表是 postgres。错误显示“带有时区的时间戳类型的输入语法无效”,但您的 sqlall 没有提及任何 timestamp with time zone,这让我相信您的数据库架构不匹配。
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 2021-09-22
  • 2018-12-18
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 2015-10-07
  • 2020-06-13
相关资源
最近更新 更多