When there is a will there’s (often) a way ![]()
According to my understanding, this is always the case:
“In Django’s admin, instances are not reused between requests. Each request is completely separate and stateless, which is a fundamental part of how HTTP and Django’s request-response cycle is designed.”
This means that you can do things with the instances without worrying that it will be reused for other tenants.
I needed to get the tenant schema name into a ModelForm init method. I then have a thread safe singleton from which I can look up all tenant data, using it’s schema name. This is how I did it. It is a kind of a hack but it uses only documented Django methods.
Can you see any problems with this?
class PlaceNameListForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
# Get the schema name from the kwargs. We must remove it before calling super(), otherwise an error will occur
tenant_schema_name = kwargs.pop('tenant_schema_name', None)
super().__init__(*args, **kwargs)
class PlaceNameListFormSet(BaseModelFormSet):
""" We used this FormSet to transfer the tenant schema name over to the PlaceNameListForm"""
def __init__(self, *args, **kwargs):
self.tenant_schema_name = ''
# Get the tenant schema name from our class name, see PlaceNameAdmin.get_changelist_formset()
class_name = self.__class__.__name__
if "_" in class_name:
prefix, tenant_schema_name = class_name.split("_", 1)
self.tenant_schema_name = tenant_schema_name
super().__init__(*args, **kwargs)
def _construct_form(self, i, **kwargs):
# Pass the tenant schema name to the form by using the kwargs
kwargs['tenant_schema_name'] = self.tenant_schema_name
return super()._construct_form(i, **kwargs)
class PlaceNameAdmin(admin.ModelAdmin):
def get_changelist_form(self, request, **kwargs):
return PlaceNameListForm
def get_changelist_formset(self, request, **kwargs):
# This is a hack to get the tenant schema name into PlaceNameListFormSet. From there it is passed to
# the PlaceNameListForm. The schema name is used to fetch correct settings for this tenant.
# I tried many other ways but this was the only one that worked. (You can't use kwargs because
# the factory methods in the Django code raises an exception if you pass in an unknown kwarg)
# Override the usual formset class with PlaceNameListFormSet and then have the super() create it
kwargs['formset'] = PlaceNameListFormSet
FormSet = super().get_changelist_formset(request, **kwargs)
# Dynamically inherit from PlaceNameListFormSet and create a new class with the schema name in the class name
tenant_schema_name = request.tenant.schema_name
class_name = f"PlaceNameListFormSet_{tenant_schema_name}"
formset_class = type(class_name, (FormSet,), {})
return formset_class
ps.
I asked ChatGPT 4 in several ways about ways to solve this, but it was unable to help me.