许多关系不存在.它处于不同的架构中

mom*_*aaa 5 python django postgresql django-models django-rest-framework

我将AbstractBaseUser与CustomPermissionsMixin一起使用.CustomPermissionsMixin与django PermissionsMixin相同,不同之处在于我为user_permissions和groups更改了related_name和related_query_name,因此它不会与django PermissionsMixin related_name冲突

@python_2_unicode_compatible
class CustomPermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(
        _('superuser status'),
        default=False,
        help_text=_(
            'Designates that this user has all permissions without '
            'explicitly assigning them.'
        ),
    )
    groups = models.ManyToManyField(
        Group,
        verbose_name=_('groups'),
        blank=True,
        help_text=_(
            'The groups this user belongs to. A user will get all permissions '
            'granted to each of their groups.'
        ),
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",
    )
    user_permissions = models.ManyToManyField(
        Permission,
        verbose_name=_('student user permissions'),
        blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",
    )

    class Meta:
        abstract = True
    ....
Run Code Online (Sandbox Code Playgroud)

我在两个不同的应用程序中拥有相同的Student类.一个在App1中,另一个在App2中,字段略有不同.我用postgresql.App1处于架构公共状态,而App2处于架构krt5jdjtrx.(使用django tenant schema.以编程方式创建)两者都使用AbstractBaseUser和CustomPermissionsMixin

class Student(AbstractBaseUser, CustomPermissionsMixin):
    ...
Run Code Online (Sandbox Code Playgroud)

我也使用DRF DjangoModelPermissions

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
        'rest_framework.permissions.DjangoModelPermissions',
Run Code Online (Sandbox Code Playgroud)

和自定义身份验证后端

class CustomBackend(ModelBackend):
    ....
Run Code Online (Sandbox Code Playgroud)

问题出_get_user_permissions在django ModelBackend里面.说user_obj是类型app1.Student, user_obj.user_permissions.all().query有时使用app1_student_user_permissionsapp2_student_user_permissions.app2_student_user_permissions如果user_obj确实是app1而不是app2,那么查询如何使用?.它会创建django.db.utils.ProgrammingError:关系不存在.

def _get_user_permissions(self, user_obj):
    print('inside _get_user_perm !!!!!!!!!!!!!!!!!!!!!!!')
    print(user_obj)
    print(type(user_obj))
    print(user_obj.user_permissions.all().query)
    return user_obj.user_permissions.all()
Run Code Online (Sandbox Code Playgroud)

这是原始查询集

SELECT "auth_permission"."id", "auth_permission"."name", "auth_permission"."content_type_id", "auth_permission"."codename" FROM "auth_permission" INNER JOIN "app2_student_user_permissions" ON ("auth_permission"."id" = "app2_student_user_permissions"."permission_id") INNER JOIN "django_content_type" ON ("auth_permission"."content_type_id" = "django_content_type"."id") WHERE "app2_student_user_permissions"."student_id" = 1 ORDER BY "django_content_type"."app_label" ASC, "django_content_type"."model" ASC, "auth_permission"."codename" ASC
Run Code Online (Sandbox Code Playgroud)

编辑

App2学生的模式/表格将在稍后的程序中创建.由于App2学生与权限有很多关系,因此权限现在具有app1关系和app2关系.我认为它是由ManyRelatedManager注册的.(权限将这两个关系视为公共架构)

如果我执行student1_of_app1.user_permissions.all(),Django将遍历Permissions所具有的关系.包括不存在的App2表.因此它会创建django.db.utils.ProgrammingError:关系不存在.

但是,有时没有错误,因为Django首先进入app1关系,但有时Django进入app2关系,因此错误.

我怎样才能防止这种情况发生?

mom*_*aaa 3

我发现问题是关于 django 租户模式而不是 django。migrate_schema --shared 实际上会迁移整个 makemigration 文件,无论共享的应用程序或租户如何。两个应用程序(共享和租户)都在django_content_type表中注册,该表也在auth_permissions. 因此,该关系不存在,因为此时尚未创建租户表,但已为权限注册了多对多关系。