tortoise / tortoise/tortoise-orm

If datetimefield is not timezone-aware get_or_create fails UNIQUE constraint.

Open
#1,556 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5.6k
Forks
516
Avg merge
2d 21h
Merged PRs (30d)
9

Description

Discussed in https://github.com/tortoise/tortoise-orm/discussions/1555

Originally posted by mmkhitaryan February 10, 2024
SELECT "sold_date","id","review","created_at","seller_id","buyer_id","purshare_type_id" FROM "purchase" WHERE "id"=94562 AND "sold_date"='2024-02-10 13:55:04' AND "review"='' AND "purshare_type_id"=1 AND "buyer_id"=2 AND "seller_id"=1 LIMIT 2

This sql query got generated before I made the sold_date timezone.make_aware()

SELECT "seller_id","purshare_type_id","sold_date","created_at","buyer_id","id","review" FROM "purchase" WHERE "id"=93707 AND "sold_date"='2024-01-29 04:16:46+00:00' AND "review"='' AND "purshare_type_id"=2 AND "buyer_id"=20 AND "seller_id"=1 LIMIT 2: None

Before I made the datetime timezone-aware, get_or_none would fail with UNIQUE CONSTRAINT error.

I want to understand, is it a bug or a feature? Because to me it sounds like a bug. IMHO tortoise should at least show warning message that the datetime field must be timezone-aware.

Making the sold_date datetime field timezone-aware fixed the problem for me: https://github.com/mmkhitaryan/odinscraper/commit/cfd1f703d034cf9a478729f18ae8608db3ab75e8#diff-e544f072d0253f9a2c630fb985108e2f779a5d5db5e7eb0cb6319304756ceee3R107

I have implemented minimal reproducible example: https://gist.github.com/mmkhitaryan/bf46cb557cae421452ba938989005b70
When you run it, you get "successfully created" message but when the datetime is naive you get error below:

(odinscraper-py3.11) @mmkhitaryan ➜ /workspaces/odinscraper/src (master) $ python mrp.py 
successfully created
Traceback (most recent call last):
  File "/home/codespace/.cache/pypoetry/virtualenvs/odinscraper-6YobV1su-py3.11/lib/python3.11/site-packages/tortoise/models.py", line 1060, in get_or_create
    await cls.select_for_update().filter(**kwargs).using_db(connection).get(),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/codespace/.cache/pypoetry/virtualenvs/odinscraper-6YobV1su-py3.11/lib/python3.11/site-packages/tortoise/queryset.py", line 1020, in _execute
    raise DoesNotExist("Object does not exist")
tortoise.exceptions.DoesNotExist: Object does not exist

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/codespace/.cache/pypoetry/virtualenvs/odinscraper-6YobV1su-py3.11/lib/python3.11/site-packages/tortoise/models.py", line 1065, in get_or_create
    return await cls.create(using_db=connection, **defaults, **kwargs), True
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/codespace/.cache/pypoetry/virtualenvs/odinscraper-6YobV1su-py3.11/lib/python3.11/site-packages/tortoise/backends/sqlite/client.py", line 38, in translate_exceptions_
    raise IntegrityError(exc)
tortoise.exceptions.IntegrityError: UNIQUE constraint failed: tortoises.name

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the get_or_create path in tortoise/models.py around lines 1060-1065, then reproduce the failure using the linked minimal example. Trace the naive and timezone-aware datetime queries through the SQLite backend in tortoise/backends/sqlite/client.py; done should mean the expected behavior is established and covered for the UNIQUE-constraint case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sqlite
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.