首页 > 解决方案 > 注释字段是 str 而不是 datetime.datetime

问题描述

例子

我正在尝试使用来自相关模型的数据来注释对象DateTimeField

    class Author(models.Model):
            name = models.CharField(max_length=256)

    class Book(models.Model):
        name = models.CharField(max_length=256)
        is_published = models.BooleanField()
        publication_date = models.DateTimeField()
        author = models.ForeignKey(Author, on_delete=models.PROTECT)

    queryset = Author.objects.annotate(
        has_unpublished=Exists(
            Book.objects.filter(
                author=OuterRef('pk'),
                is_published=False))
    ).annotate(
        last_published_date=Max(
            'book__publication_date',
            filter=Q(book__is_published=True)
        )
    )

sqlite3我在默认本地数据库和MySQL(with mysqlclient)之间交替。SQLite 工作,MySQL 崩溃。

原因如下:两个数据库的编译器

results = compiler.execute_sql(**kwargs)

返回 int 和 string 元组列表的列表,如下所示:

SQLite

<class 'list'>: [[(1, 'Alice', 1, '2017-01-01 01:00:00'), (2, 'Bob', 0, '2019-01-05 13:00:00'), (3, 'Carol', 1, None), (4, 'Dan', 0, None)]]

MySQL

<class 'list'>: [((1, 'Alice', 1, '2017-01-01 01:00:00.000000'), (2, 'Bob', 0, '2019-01-05 13:00:00.000000'), (3, 'Carol', 1, None), (4, 'Dan', 0, None))]

现在,当 SQLite 后端看到一个假定的日期时间字段时,它会在运行时使用此方法生成一个转换器:

django.db.backends.sqlite3.operations.DatabaseOperations

    def convert_datetimefield_value(self, value, expression, connection):
        if value is not None:
            if not isinstance(value, datetime.datetime):
                value = parse_datetime(value)
            if settings.USE_TZ and not timezone.is_aware(value):
                value = timezone.make_aware(value, self.connection.timezone)
        return value

这工作正常。

然而,MySQL 后端会这样做:

django.db.backends.mysql.operations.DatabaseOperations

    def convert_datetimefield_value(self, value, expression, connection):
        if value is not None:
            value = timezone.make_aware(value, self.connection.timezone)
        return value

然后 Django 继续崩溃,试图检查<str>时区感知。

语境

以上是我用来重现崩溃的玩具示例。

在我们的实际生产环境中execute_sql,奇怪的是,如果我请求带datetime.datetime注释的作者的完整列表(action=='list'一个(action=='retrieve')。查询集各自的 sql 查询仅因存在单个 WHERE 子句而有所不同。

这让我认为我做错了什么并且没有得到datetime.datetime我应该从驱动程序中获得的原始数据(而不是 Django 中出现错误的可能性要低得多)。

我应该怎么办?N+1 是不可能的,这将是应用程序的主要操作员视图,并且 datetime 字段实际上是两个深度的一对多关系。

标签: pythondjangomysql-pythondjango-annotatedjango-mysql

解决方案


推荐阅读