Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field 'DatetimeField' has error when I use '__year' or '__month'. report this:" 'int' object has no attribute 'utcoffset' " #1575

Closed
h2magic-axious opened this issue Mar 26, 2024 · 2 comments

Comments

@h2magic-axious
Copy link

Describe the bug
This is my model:

class Transfer(AbstractModel):
    class Meta:
        table = "transfer"

    account = fields.ForeignKeyField("models.Account", related_name="transfers")
    category = fields.ForeignKeyField("models.Category")

    title = fields.CharField(max_length=30)
    amount = fields.DecimalField(max_digits=10, decimal_places=2)
    remark = fields.CharField(max_length=128, default="")
    created_at = fields.DatetimeField(auto_now_add=True)

To Reproduce
This is filter:

@router.get("/test")
async def test_all_transfers():
    transfers = await Transfer.filter(created_at__year=2024)
    return response_success(transfers)

Expected behavior
I get follow:

AttributeError: 'int' object has no attribute 'utcoffset'

Additional context
this is full stack:

ERROR:    Exception in ASGI application
  + Exception Group Traceback (most recent call last):
  |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\_utils.py", line 87, in collapse_excgroups
  |     yield
  |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\base.py", line 190, in __call__
  |     async with anyio.create_task_group() as task_group:
  |   File "D:\coding\money-manage\venv\Lib\site-packages\anyio\_backends\_asyncio.py", line 678, in __aexit__
  |     raise BaseExceptionGroup(
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "D:\coding\money-manage\venv\Lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 407, in run_asgi
    |     result = await app(  # type: ignore[func-returns-value]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 69, in __call__
    |     return await self.app(scope, receive, send)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
    |     await super().__call__(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\applications.py", line 123, in __call__
    |     await self.middleware_stack(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
    |     raise exc
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
    |     await self.app(scope, receive, _send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\base.py", line 189, in __call__
    |     with collapse_excgroups():
    |   File "C:\Python312\Lib\contextlib.py", line 158, in __exit__
    |     self.gen.throw(value)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\_utils.py", line 93, in collapse_excgroups
    |     raise exc
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\base.py", line 191, in __call__
    |     response = await self.dispatch_func(request, call_next)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\main.py", line 68, in process_before_request
    |     return await call_next(request)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\base.py", line 165, in call_next
    |     raise app_exc
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\base.py", line 151, in coro
    |     await self.app(scope, receive_or_disconnect, send_no_error)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\cors.py", line 83, in __call__
    |     await self.app(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\middleware\exceptions.py", line 62, in __call__
    |     await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
    |     raise exc
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    |     await app(scope, receive, sender)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\routing.py", line 758, in __call__
    |     await self.middleware_stack(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\routing.py", line 778, in app
    |     await route.handle(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\routing.py", line 299, in handle
    |     await self.app(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\routing.py", line 79, in app
    |     await wrap_app_handling_exceptions(app, request)(scope, receive, send)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
    |     raise exc
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
    |     await app(scope, receive, sender)
    |   File "D:\coding\money-manage\venv\Lib\site-packages\starlette\routing.py", line 74, in app
    |     response = await func(request)
    |                ^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\fastapi\routing.py", line 278, in app
    |     raw_response = await run_endpoint_function(
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\fastapi\routing.py", line 191, in run_endpoint_function
    |     return await dependant.call(**values)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\routers\transfer.py", line 17, in test_all_transfers
    |     transfers = await Transfer.filter(created_at__year=2024)
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\queryset.py", line 1000, in __await__
    |     self._make_query()
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\queryset.py", line 962, in _make_query
    |     self.resolve_filters(
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\queryset.py", line 134, in resolve_filters
    |     modifier &= node.resolve(model, model._meta.basetable)
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\expressions.py", line 359, in resolve
    |     return self._resolve_kwargs(model, table)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\expressions.py", line 321, in _resolve_kwargs
    |     filter_modifier = self._resolve_regular_kwarg(model, key, value, table)
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\expressions.py", line 280, in _resolve_regular_kwarg
    |     criterion, join = self._process_filter_kwarg(model, key, value, table)
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\expressions.py", line 265, in _process_filter_kwarg
    |     else model._meta.db.executor_class._field_to_db(field_object, value, model)
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\backends\base\executor.py", line 198, in _field_to_db
    |     return field_object.to_db_value(attr, instance)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\fields\data.py", line 383, in to_db_value
    |     if timezone.is_naive(value):
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "D:\coding\money-manage\venv\Lib\site-packages\tortoise\timezone.py", line 84, in is_naive
    |     return value.utcoffset() is None
    |            ^^^^^^^^^^^^^^^
    | AttributeError: 'int' object has no attribute 'utcoffset'
    +------------------------------------
@waketzheng
Copy link
Contributor

Change line 381 in tortoise/fields/data.py from if value is not None to if isinstance(value, datetime.datetime)
image

@abondar
Copy link
Member

abondar commented May 24, 2024

Fixed in 0.21.0

@abondar abondar closed this as completed May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants