You can quickly build a multi-tenant site in Django with the help of this nifty package django-tenant-schemas. It works by assigning each tenant into its own database schema and having one public schema for anything that needs to be shared.

It wraps Django's connection with its own wrapper that help to route connection request accordingly based on the hostname tenant1.domain.com to schema tenant1. So this works great when you're in the context of Django application.

I have Celery task that needs to be run and needs to access the database. I could just pass the model directly to the Celery task params but it is not advisable to do so.

In my views.py:

class StandardReport(APIView):  
    def get(self, request, format=None):
        site = Site.objects.first()
        run_report.delay(site.id)
        return Response(site.name)

and in my tasks.py, I have

@shared_task
def run_report(title, site_id):  
    # we need this
    # c = connection.cursor()
    # c.db.set_schema('myschema')

    site = Site.objects.get(pk=site_id)
    return site.name

If I don't have the commented lines, it won't work because it is hitting public schema and the tables do not exist in public schema.

Note: We can use set_schema because that was the function available in the wrapper that was used internally by the package to handle switching of the schema.