I'm using django as an API server(using DRF) and admin dashboard with Postgres DB. The problem is I'll have multiple tenants and I want to follow a total separation of concern flow. Data from one tenant should not in any way be accessible to the other.
Example Scenario: Say I have multiple Institutes as my clients and every institute will have all of their students onboarded on my platform. No institute should be able to access other's data.
I can think of 2 approaches:
1. Extending ModelAdmin for Admin pages and for the APIs I can get the tenant associated to a particular user from the request.
In this approach, I'll have to check for the tenant of a user in every modelAdmin class and get a filtered queryset in the def get_queryset() method
def get_queryset(self, request):
tenant = request.user.tenant # using related_name of foreignkey
queryset = Course.objects.filter(tenant_id=tenant)
And have to do this similarly in the list, create, update and destroy methods of the ModelViewSet class while creating APIs
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
permission_classes = (DjangoModelPermissions,)
def list(self, request, *args, **kwargs):
tenant = request.user.tenant
queryset = self.filter_queryset(self.get_queryset())
queryset = queryset.filter(tenant__id=tenant)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
def create(self, request, *args, **kwargs):
pass
def update(self, request, *args, **kwargs):
pass
def destroy(self, request, *args, **kwargs):
pass
2. Using Row Level Security provided by Postgres
In this approach all the filtering will be done by postgres itself, but for this to work, I'll have to create a middleware that sets the (postgres) session variable, and a mechanism to enable/disable this on a model.
More about this approach can be found in the link below:
https://schinckel.net/2017/12/20/django-multitenancy-using-postgres-row-level-security/
Please suggest which approach will be better among the two above and if there's any better approach of doing this.
Note: It's a requirement to keep all the data of all the clients in the same DB in the same Schema.