djangomulti-tenantdjango-tenants

Django-tenants: Accessing tenant data in public domain


I was working on Django-tenant where I have tenant model called Appointment now I want to get the appointment of a specific tenant from the public domain but I'm having an issue when rendering it in the template

class OrganizationAppointmentList(LoginRequiredMixin, TenantMixin, ListView):
    template_name = 'main/appointments/list_appointment.html'
    paginate_by = 10

    def get_queryset(self):
        tenant_id = self.kwargs.get('pk')
        try:
            tenant = Organization.objects.get(id=tenant_id)
            self.schema_name = tenant.schema_name
            with schema_context(self.schema_name):
                queryset = Appointment.objects.all()
                return queryset
        except Organization.DoesNotExist:
            raise Http404("Tenant not found")
        except Exception as e:
            raise Http404(f"Error accessing tenant data: {e}")

    def paginate_queryset(self, queryset, page_size):
        with schema_context(self.schema_name):
            return super().paginate_queryset(queryset, page_size)

    def get_context_data(self, **kwargs):
        with schema_context(self.schema_name):
            context = super().get_context_data(**kwargs)
            tenant_id = self.kwargs.get('pk')
            context['tenant_id'] = tenant_id
            context['appointments'] = Appointment.objects.all()
            print(context['appointments'])
            return context

In above code the print(context['appointments']) Is giving the exact data but while rendering it in template it shows

relation "appointment_app_appointment" does not exist
LINE 1: ...app_appointment"."al_appointment_updated_at" FROM "appointme...

and if I left the template empty the error does not show is it something that I'm missing??

I'm trying to get the specific tenant model data in public domain


Solution

  • Querysets are lazy, meaning the actual model instances inside the queryset you can see in your print statement aren't actually loaded into memory at that time.

    That, coupled with the fact that the schema context isn't passed along to the template engine, means that when the template tries to access items from the queryset, it does so with whatever schema the public instance uses. The tenant-model doesn't exist in the public schema, which then leads to the error you are seeing.

    Fix: Force-evaluate the queryset to force its elements, and do so inside the schema context block.

    For example:

    with schema_context(self.schema_name):
        ...
        list(context['appointments'] = Appointment.objects.all())
    

    NB! Be wary that this means the template can only access data explicitly contained in the queryset at the time of evaluation. Which is to say that you cannot traverse relationships inside the template if you do it this way, because that requires the templating engine to make database calls (leading to the same schema-problems as with the original error).

    So make sure that your queryset explicitly contains all the requisite data the template needs.