一种Django多租户解决方案 (4)

因为经过我们的改造django 已经支持动态增加数据库连接,因此可以在migrate --database参数指定一个数据库连接别名,migrate命令会自行判断,如果不存在会创建

rest_framework适配 认证

我们需要在rest_framework完成认证之后,增加判断用户是否属于某个租户的逻辑即可

from rest_framework.request import Request from rest_framework import exceptions from multi_tenant.local import set_current_db def __request_authenticate(self): """ Attempt to authenticate the request using each authentication instance in turn. """ for authenticator in self.authenticators: try: user_auth_tuple = authenticator.authenticate(self) except exceptions.APIException: self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple if self.user and self.user.tenant: set_current_db(self.user.tenant.code) return self._not_authenticated() Request._authenticate = __request_authenticate 权限

因为request.user现在是GlobalUser,因此没有has_perms方法,因此rest_framework.permissions的IsAdminUser、DjangoModelPermissions、DjangoObjectPermissions权限类,需要将request.user的GlobalUser相关的逻辑判断切换为django.contrib.auth.User对象,

这里以DjangoModelPermissions为例

rest_framework 原始的权限类

class DjangoModelPermissions(BasePermission): ... def has_permission(self, request, view): # Workaround to ensure DjangoModelPermissions are not applied # to the root view when using DefaultRouter. if getattr(view, \'_ignore_model_permissions\', False): return True if not request.user or ( not request.user.is_authenticated and self.authenticated_users_only): return False queryset = self._queryset(view) perms = self.get_required_permissions(request.method, queryset.model) return request.user.has_perms(perms)

转化之后的权限类

class DjangoModelPermissions(BasePermission): def has_permission(self, request, view): username = request.user.username current_user = None try: current_user = self.TenantUser.objects.filter(is_active=True).get(username=username) except self.TenantUser.DoesNotExist: return False if getattr(view, \'_ignore_model_permissions\', False): return True if not request.user or ( not request.user.is_authenticated and self.authenticated_users_only): return False queryset = self._queryset(view) perms = self.get_required_permissions(request.method, queryset.model) return current_user.has_perms(perms)

至此django多租户改造的核心已经完成改造,可以完整的使用django所有功能,完美兼容rest_framework及其第三方插件。

插件使用 pip install django-multi-tenancy

使用方式详见,源码README

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgywjf.html