Tortoise-orm: Add a possibility to use naive fields.DatetimeField

Created on 25 Nov 2020  路  2Comments  路  Source: tortoise/tortoise-orm

With tortoise-orm v0.16.18 released it's impossible to use naive TIMESTAMP without timezone support (especially in PostgreSQL).

I'd want to have a possibility to proceed either with naive timestamps, or with aware timestamps based on some flag.
A good example would be sqlalchemy.TIMESTAMP's with optional timezone flag.

In this case upgrade from v0.16.17 to v0.16.18 could be done without breaking changes.

Currently I have such a solution (use own fields.DatetimeField):

import datetime
from typing import Any, Optional, Type, Union

from tortoise import fields
from tortoise.models import Model


def to_naive(value: datetime.datetime) -> datetime.datetime:
    if value.tzinfo is None:
        return value

    value = value.astimezone(datetime.timezone.utc)

    return value.replace(tzinfo=None)


class NaiveDatetimeField(fields.DatetimeField):
    skip_to_python_if_native = True

    class _db_postgres:  # noqa
        SQL_TYPE = "TIMESTAMP"

    def to_python_value(self, value: Any) -> Optional[datetime.datetime]:
        value = super().to_python_value(value)

        if value is None:
            return value

        return to_naive(value)

    def to_db_value(
        self,
        value: Optional[datetime.datetime],
        instance: "Union[Type[Model], Model]",
    ) -> Optional[datetime.datetime]:
        value = super().to_db_value(value, instance)

        if value is None:
            return value

        return to_naive(value)

But, of course, it's nothing more than workaround, not a proper solution.

Another solution would be to create a migration:

ALTER TABLE my_table ALTER COLUMN datetime_col TYPE timestamptz;

But that's even worse because it forces the unwanted changes to the database structure.

Most helpful comment

Faced the same issue. Aerich creates fields of type TIMESTAMP with use_tz=False for DateTimeField(auto_now_add=True). But tortoise generates offset-aware datetime object that causes the error:

tortoise.exceptions.OperationalError: invalid input for query argument $1: datetime.datetime(2020, 12, 4, 10, 35, 4... (can't subtract offset-naive and offset-aware datetimes)

All 2 comments

Faced the same issue. Aerich creates fields of type TIMESTAMP with use_tz=False for DateTimeField(auto_now_add=True). But tortoise generates offset-aware datetime object that causes the error:

tortoise.exceptions.OperationalError: invalid input for query argument $1: datetime.datetime(2020, 12, 4, 10, 35, 4... (can't subtract offset-naive and offset-aware datetimes)

How did you solve this problem? I'm facing it as well and don't know what to do..

Was this page helpful?
0 / 5 - 0 ratings