tortoise / tortoise/tortoise-orm
How to implement multi tenant application using tortoise-orm with postgres schema per tenant
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 516
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 9
Description
Problem Definition
I'm trying to use tortoise-orm to build a multi-tenant application using postgres schema.
I've two models:
- Tenant: Tenant model will be kept in the default/public schema of the postgres database. And it'll have the following structure:
class Tenant(Model):
name = fields.CharField(max_length=150)
host_name = fields.CharField(max_length=100)
tenant_schema_name = fields.CharField(max_length=200, null=True)
db_url = fields.CharField(max_length=200, null=True)
class Meta:
table = "tenant"
And it'll be saved in the public schema of the postgres database.
- User: User model will be kept in the non default schema of the database. And this schema name will be used from the
tenant_schema_namefield for a specific tenant record. For instance, when a new tenant will be created with thetenant_schema_name=tenant_1234then we'll create a new database schema with the nametenant_1234and will try to migrate theUsermodel into that schema. User model will have following structure:
class User(Model):
email = fields.CharField(
max_length=50, unique=True,
validators=[RegexValidator("([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+", re.I)]
)
first_name = fields.CharField(max_length=100, null=True)
last_name = fields.CharField(max_length=100, null=True)
password = fields.CharField(max_length=128, null=False)
date_joined = fields.DatetimeField(auto_now_add=True, use_tz=False, null=True)
last_login_at = fields.DatetimeField(auto_now=True, use_tz=False, null=True)
status = fields.CharEnumField(StatusChoices, default=StatusChoices.UNVERIFIED)
class Meta:
table = "user"
I tried to manually create database schema and set the schema search path to the tenant specific schema. And then tried to create the User record but it is creating the user record into the default/public schema instead of tenant specific schema.
I tried to use schema attribute of the Model.Meta but it seems having no effect.
I tried to use db_url with optional parameter schema=tenant for Tortoise.init but still it can not create record on the tenant specific schema.
I found no work around to use database schema to implement multi tenancy with postgres schemas and tortoise-orm.
I've the Tortoise init configuration as follows:
TORTOISE_ORM = {
"connections": {
"public": "postgres://root:admin@127.0.0.1:5432/root",
"tenants": "postgres://root:admin@127.0.0.1:5432/root"
},
"apps": {
"public": {
"models": ["apps.tenants.models", "aerich.models"],
"default_connection": "public",
},
"tenants": {
"models": ["apps.users.models"],
"default_connection": "tenants",
}
},
}
So, I want to know if there is any way to set database schema for a database connection client with tortoise-orm?
And I'm also interested to know if there is any way to dynamically change database models Meta attribute for instance, if it is possible to update table=users instead of keeping it as table=user for the above User model?
I was trying something similar with tortoise-orm that is described here
@long2ice @grigi
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the TORTOISE_ORM configuration and the models in apps.tenants.models and apps.users.models, then trace how Tortoise.init handles connection schema settings and Model.Meta.schema. Compare the behavior with the reported public-schema writes. Done would be a documented, supported approach for per-tenant PostgreSQL schemas or a clear statement that this use case is not supported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, python
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100