Skip to content

Commit 0a410a7

Browse files
committed
feat(django): added shell with tenant arg
1 parent 7fc6183 commit 0a410a7

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "cardo-python-utils"
7-
version = "0.5.dev48"
7+
version = "0.5.dev49"
88
description = "Python library enhanced with a wide range of functions for different scenarios."
99
readme = "README.rst"
1010
requires-python = ">=3.8"

python_utils/django/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,30 @@ admin.site.has_permission = has_admin_site_permission
155155

156156
If using `django-ninja`, apart from the settings configured above, auth utils are provided in the django/api/ninja.py module.
157157

158+
## Atomic Transactions
159+
160+
Django's `transaction.atomic` uses the default database. To make it tenant-aware, use `tenant_atomic`
161+
162+
```python3
163+
from python_utils.django.db.transaction import tenant_atomic
164+
165+
@tenant_atomic
166+
def my_function():
167+
...
168+
```
169+
170+
## Django Shell
171+
172+
This library overrides the shell command of Django, so that it requires the `tenant` arg.
173+
This way, the shell is automatically initialized with the context set to the tenant.
174+
175+
```bash
176+
./manage.py shell --tenant=tenant1
177+
178+
Starting shell for tenant: -tenant=tenant
179+
>>>
180+
```
181+
158182
## Testing
159183

160184
In order for tests to work, create the following autouse fixtures:
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from django.core.management.commands.shell import Command as ShellCommand
2+
3+
from ...settings import TENANT_DATABASES
4+
from ...tenant_context import TenantContext
5+
6+
7+
class Command(ShellCommand):
8+
help = "Runs a Python interactive interpreter for a specific tenant."
9+
10+
def add_arguments(self, parser):
11+
super().add_arguments(parser)
12+
13+
parser.add_argument(
14+
"--tenant",
15+
action="store",
16+
dest="tenant",
17+
help="Specify the tenant to run the shell for.",
18+
required=True,
19+
type=str,
20+
)
21+
22+
def handle(self, **options):
23+
tenant = options["tenant"]
24+
25+
if tenant not in TENANT_DATABASES:
26+
self.stdout.write(self.style.ERROR(f"Tenant '{tenant}' not found in DATABASES settings."))
27+
return
28+
29+
self.stdout.write(self.style.SUCCESS(f"Starting shell for tenant: {tenant}"))
30+
31+
with TenantContext(tenant):
32+
super().handle(**options)

0 commit comments

Comments
 (0)