How to handle teardown using django-tenant?
I'm using django-tenant and having trouble when i try to create my tests.
I had to create a setup_tenant class to create a teardown before testing, because to access the restaurant table, I had to create the tenant upstream. However, when my tests finish successfully, I get an error during teardown:
ERROR restaurants/tests.py::RestaurantTests::test_update_restaurant - django.db.utils.ProgrammingError: relation "restaurants_restaurant" does not exist
This is the full error:
restaurants/tests.py::RestaurantTests::test_update_restaurant PASSED [100%]
restaurants/tests.py::RestaurantTests::test_update_restaurant ERROR [100%]
======================================================================================================= ERRORS =======================================================================================================
____________________________________________________________________________ ERROR at teardown of RestaurantTests.test_update_restaurant _____________________________________________________________________________
self = <django.db.backends.utils.CursorWrapper object at 0x108b084a0>
sql = 'SELECT "restaurants_restaurant"."id", "restaurants_restaurant"."name", "restaurants_restaurant"."owner_id", "restaura... "restaurants_restaurant"."tenant_id" FROM "restaurants_restaurant" WHERE "restaurants_restaurant"."tenant_id" IN (%s)'
params = (1,), ignored_wrapper_args = (False, {'connection': <DatabaseWrapper vendor='postgresql' alias='default'>, 'cursor': <django.db.backends.utils.CursorWrapper object at 0x108b084a0>})
def _execute(self, sql, params, *ignored_wrapper_args):
# Raise a warning during app initialization (stored_app_configs is only
# ever set during testing).
if not apps.ready and not apps.stored_app_configs:
warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning)
self.db.validate_no_broken_transaction()
with self.db.wrap_database_errors:
if params is None:
# params default might be backend specific.
return self.cursor.execute(sql)
else:
> return self.cursor.execute(sql, params)
This is my Restaurant model:
from customer.models import CustomerTenant
class Restaurant(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(User, related_name="restaurants", on_delete=models.CASCADE)
description = models.TextField(blank=True, default="")
created_at = models.DateTimeField(auto_now_add=True)
tenant = models.ForeignKey(CustomerTenant, on_delete=models.CASCADE, related_name="restaurants")
def __str__(self):
return self.name`
This is my tenant model
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django_tenants.models import DomainMixin, TenantMixin
class CustomerTenant(TenantMixin):
name = models.CharField(max_length=255)
owner = models.OneToOneField("auth.User", on_delete=models.CASCADE, related_name="owned_tenant")
created_on = models.DateField(auto_now_add=True)
# Required fields for django-tenants
auto_create_schema = settings.TENANTS.get("AUTO_CREATE_SCHEMA", True)
auto_drop_schema = settings.TENANTS.get("AUTO_DROP_SCHEMA", False)
def __str__(self):
return self.name
class Domain(DomainMixin):
tenant = models.ForeignKey("CustomerTenant", on_delete=models.CASCADE, related_name="domains")
domain = models.CharField(max_length=255, unique=True)
is_primary = models.BooleanField(default=False) # Support multiple domains per tenant
def __str__(self):
return self.domain
def clean(self):
# Ensure only one primary domain per tenant
if self.is_primary and Domain.objects.filter(tenant=self.tenant, is_primary=True).exists():
raise ValidationError("Only one primary domain is allowed per tenant.")
This is my tests:
from django.contrib.auth.models import User
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework_simplejwt.tokens import RefreshToken
from django.core.management import call_command
from django_tenants.test.cases import TenantTestCase
from django_tenants.test.client import TenantClient
from django.db import connection
from api.models import UserProfile
from order.models import Priority
from .models import Ingredient, Product, ProductFilter, Restaurant, Version
class RestaurantTests(TenantTestCase, APITestCase):
@classmethod
def setup_tenant(cls, tenant):
"""
Add any additional setting to the tenant before it gets saved.
This is required if you have required fields.
"""
call_command("createadmin", username="admin", email="admin@example.com", password="password")
tenant.owner_id = 1
return tenant
def setUp(self):
super().setUp()
self.user1 = User.objects.get(username="admin")
UserProfile.objects.create(user=self.user1, role="owner", restaurant=None)
self.user2 = User.objects.create_user(username="user2", password="password123")
UserProfile.objects.create(user=self.user2, role="owner", restaurant=None)
self.client = TenantClient(self.tenant)
# Log in user1 and get the JWT token
self.token = self.get_jwt_token(self.user1)
self.client.default_format = "json"
Someone know why teardown can't handle my test ending ?