Просто нужна помощь, чтобы перелезть через стену, на которую я наткнулся.
У меня есть веб-приложение, которому при каждой регистрации пользователя назначается лицензия. К этой лицензии прикреплены CustomPermissions, сообщающие, к каким значениям поля в материализованном представлении они имеют доступ. У меня есть API, который должен фильтровать данные, запрашиваемые пользователем, который запросил их, на основе лицензии пользователя. Ниже я нарисовал несколько примеров моделей, в которых изложена моя проблема.
class CustomPermission(models.Model):
name = models.CharField(max_length=255)
field = models.CharField(max_length=255)
value = models.CharField(max_length=255)
class License(models.Model):
name = models.CharField(max_length=255)
permissions = models.ManyToManyField(CustomPermissions)
...
class User(AbstractBaseUser):
license = models.ForeignKey(License, on_delete=models.CASCADE)
...
Это отлично работает, если я фильтрую только столбцы с текстовыми значениями. Я могу просто сделать
...
user = request.user
permissions = user.license.permissions.values_list('field', 'value')
return queryset.objects.filter(**{field: value for field, value in permissions})
Эта проблема заключается в том, что я не могу фильтровать по другим типам данных (например, по дате). Например, если бы я хотел ограничить доступ к данным, опубликованным за последние 90 дней, это невозможно представить в этой модели.
Чтобы решить эту проблему, я подумал об использовании разреженной таблицы для модели CustomPermission. Что-то вроде
class CustomPermission(models.Model):
name = models.CharField(max_length=255)
field = models.CharField(max_length=255)
operation = models.CharField(max_length='32')
text_value = models.CharField(max_length=255, null=True, blank=True)
date_value = models.DateField(null=True, blank=True)
Где операция равна '__gt', '__lt', ... et c, text_value - текстовое значение, а date_value - date_value. Затем я бы сделал что-то похожее на приведенное выше с
...
user = request.user
permissions = user.license.permissions.values_list('field', 'operation', 'text_value', 'date_value')
return queryset.objects.filter(**{fld+op: txt_val or dat_val for fld, op, txt_val, dat_val in permissions})
, но это кажется неправильным и может быстро стать беспорядочным. Есть предложения?