tortoise / tortoise/tortoise-orm

Allow validators to run async and do database IO

Open
#1,025 1 comment 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

Is your feature request related to a problem? Please describe.
I have a need to do some complex validation, where I need to enforce uniqueness with a condition through a join. This isn't possible with partial indexes etc. as the condition is through a join, which doesn't work.

The specific use case is to enforce that a phone line does not have more than one primary phone number with "active" set to true - the data model is something like the below:

class Line(Model):
  id = IntField(pk=True)
  mappings: ReverseRelation["Mappings"])

class Number(Model):
  id = IntField(pk=True)
  number = CharField(255, index=True, unique=True)
  active = BooleanField(default=True)
  mappings: ReverseRelation["LineNumberMapping"]

class LineNumberMapping(Model):
  id = IntField(pk=True)
  primary = BooleanField(default=True)

  line = ForeignKeyField("Line", related_name="mappings")
  number = ForeignKeyField("Number", related_name="mappings")

I'm migrating my application from Rails, and achieve this in Rails by doing a database query in a validator - though I am open to being told that this isn't the right pattern for tortoise-orm.

Describe the solution you'd like
In order to do this, I'd like to use a validator to query the database to find out if any rows match a query, and then error if so - however validators are run sync, so I cannot await a query on the DB.

Describe alternatives you've considered
I've considered implementing the constraint in the DB with regular constraints - but this isn't possible.
I've also considered using a trigger, but would prefer to keep this in the application if possible.

Additional context
None right now.

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 by tracing the validator execution path and how model validation is invoked, then review the async database-query APIs. Define how an awaited validator reports errors and how validation is scheduled; done means an async validator can perform the requested query and reject invalid data without breaking existing synchronous validators. Add coverage for the join-based uniqueness case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.