两个应用程序在 sqllite3 DATEFIELD 上存在分歧——哪个是正确的?

发布于 2024-10-20 15:57:19 字数 1021 浏览 2 评论 0原文

我在处理 Digikam(照片管理软件)Django(Python Web 框架) 之间的 sqllite3 DATEFIELD 时遇到不兼容问题。我遇到这个问题是因为我正在尝试编写一个 Django 应用程序,它将根据我的 Digikam 数据库为我的照片集提供网页界面。

数据库是由 Digikam 创建的,所有的 DATEFIELDS 都是这样的格式(使用 SQLite 数据库浏览器查看表):

**2011-02-06T19:06:28**

当 Django 存储日期时(使用 Django DateTime 字段),数据库中的格式是:

**2011-03-04 00:24:07.013620**

Django chokes每当它遇到Digikam 创建的日期/时间:

/usr/lib/python2.6/dist-packages/django/db/backends/util.py in typecast_date(s)
     58 
     59 def typecast_date(s):
---> 60     return s and datetime.date(*map(int, s.split('-'))) or None # returns None if s is null
     61 
     62 def typecast_time(s): # does NOT store time zone information

ValueError: invalid literal for int() with base 10: '03T15:53:14'

因此,这提出了一些问题:

  1. 这些日期格式中哪些是有效的?
  2. sqllite 不验证日期时间输入吗?
  3. 有没有一种简单的方法可以让 Django 愉快地读取 Digikam 格式的日期?

谢谢你!

I am running into an incompatibility in the handling of the sqllite3 DATEFIELD between Digikam (photo management software) and Django (a python web framework). I encountered the problem because I'm trying to write a Django application which will provide a webpage interface to my photo collection based on my Digikam database.

The database was created by Digikam and all of the DATEFIELDS are in this format (using SQLite Database Browser to view the tables):

**2011-02-06T19:06:28**

When Django stores dates (using the Django DateTime field), the format in the database is:

**2011-03-04 00:24:07.013620**

Django chokes whenever it encounters the date/times created by Digikam:

/usr/lib/python2.6/dist-packages/django/db/backends/util.py in typecast_date(s)
     58 
     59 def typecast_date(s):
---> 60     return s and datetime.date(*map(int, s.split('-'))) or None # returns None if s is null
     61 
     62 def typecast_time(s): # does NOT store time zone information

ValueError: invalid literal for int() with base 10: '03T15:53:14'

So, this brings up a few questions:

  1. Which of these date formats is valid?
  2. Doesn't sqllite validate datetime input?
  3. Is there an easy way to get Django to happily read the Digikam format dates?

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

初见你 2024-10-27 15:57:20

我也遇到了同样的挫败感。我最终在 models.py 中编写了以下猴子补丁,它为我“解决”了问题:

# -------------------------------------------------------------                                                       
# Monkeypatch date parser to be friendly with Digikam SQLite                                                          
# -------------------------------------------------------------                                                       

import django.db.backends.util                                                                                        
orig_typecast_date = django.db.backends.util.typecast_date                                                            
def monkeypatch_typecast_date(s):                                                                                     
    if s and 'T' in s:                                                                                                
        s = s[:s.find('T')]                                                                                           
    return orig_typecast_date(s)                                                                                      
django.db.backends.util.typecast_date = monkeypatch_typecast_date     

I hit this exact same frustration. I ended up writing the following monkey patch in my models.py which "solved" the problem for me:

# -------------------------------------------------------------                                                       
# Monkeypatch date parser to be friendly with Digikam SQLite                                                          
# -------------------------------------------------------------                                                       

import django.db.backends.util                                                                                        
orig_typecast_date = django.db.backends.util.typecast_date                                                            
def monkeypatch_typecast_date(s):                                                                                     
    if s and 'T' in s:                                                                                                
        s = s[:s.find('T')]                                                                                           
    return orig_typecast_date(s)                                                                                      
django.db.backends.util.typecast_date = monkeypatch_typecast_date     
君勿笑 2024-10-27 15:57:20

两种格式都是合理的日期表示形式。 SQLite 没有本机日期时间类型,但具有许多用于处理存储为实数、整数或文本对象的日期/时间的函数(请参阅 http://www.sqlite.org/datatype3.html)。

鉴于 Django 和 Digicam 选择处理不同格式的日期,您最好的方法可能是编写一个新的模型字段类型,可以处理 Digikam 使用的日期格式(http://docs.djangoproject.com/en/dev/howto /自定义模型字段/)。如果您所做的只是读取 Digikam 数据库,那么这非常简单 - 您只需编写一些代码即可将表示形式转换为 Python Datetime 对象,您可能可以使用 Python 的 <代码> datetime.strptime 函数(http://docs.python.org/library/datetime.html#datetime.datetime.strptime)。

Both formats are reasonable date representations. SQLite doesn't have a native datetime type, but rather has a number of functions for dealing with dates/times stored as reals, ints, or text objects (see http://www.sqlite.org/datatype3.html).

Given that Django and Digicam choose to handle dates in different formats, your best route is probably to write a new model field type that can handle the date format used by Digikam (http://docs.djangoproject.com/en/dev/howto/custom-model-fields/). If all you're doing is reading the Digikam dtabase, this is pretty easy--you'll just have to code a bit to convert the representation into a Python Datetime object, which you'll probably be able to do using the Python's datetime.strptime function (http://docs.python.org/library/datetime.html#datetime.datetime.strptime).

浮生面具三千个 2024-10-27 15:57:20

关于2):据我所知,sqlite 不进行任何输入验证。查看 sqlite 文档,我看到了这一点:

SQLite 没有存储类
留出空间用于存储日期和/或
次。相反,内置的 Date And
SQLite 的时间函数能够
将日期和时间存储为 TEXT,
REAL 或 INTEGER 值:

TEXT 作为 ISO8601 字符串 ("YYYY-MM-DD
时:分:SS.SSS")。

...

从我的阅读来看,Digikam 是一个不遵守(非常软的)sqlite 规则的游戏。(可能是因为当作者在编写代码时,你所描述的内容并不在作者的脑海中) 根据您的工作流程

,我可以想到一些选项,但没有一个非常令人满意:

  • 修改 Digicam 代码以输出类似于 SQLite 在其文档中宣传的日期的文本格式。
  • 修改 Django 代码以解析该日期格式。
  • 在数据库中创建一个视图,使用[日期操作](http://www.sqlite.org/lang_datefunc.html)函数之一来转换该列,并让 django 使用该视图

前两个相当复杂/难以维护,第三个似乎不需要太多麻烦就可以实现。

如果您实际上没有为两个应用程序使用相同的数据库(而是副本),最后一个解决方法是编写一个简单的脚本来批量转换该列。不“漂亮”,但应该有用。

Regarding 2): sqlite doesn't do any input validation as far as I know. Looking at the sqlite docs, I see this:

SQLite does not have a storage class
set aside for storing dates and/or
times. Instead, the built-in Date And
Time Functions of SQLite are capable
of storing dates and times as TEXT,
REAL, or INTEGER values:

TEXT as ISO8601 strings ("YYYY-MM-DD
HH:MM:SS.SSS").

...

So from my reading, Digikam is the one that's not playing by the (very soft) sqlite rules. (Probably because what you are describing was not in the authors' mind when they built their database).

Depending on your workflow for this, there are a few options I can think of, none very satisfying:

  • modify the Digicam code to output something like the TEXT format for Date that SQLite advertises in its docs.
  • modify the Django code to parse that date format.
  • create a view in your database, using one of the [date manipulation](http://www.sqlite.org/lang_datefunc.html) functions to convert that column, and have django use that view

The first two are rather complex/hard to maintain, the third one seems doable without too much hassle.

A last workaround, if you're not actually using the same database (but a copy) for both apps is to write a simple script to convert that column wholesale. Not "pretty", but should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文