Django - запрос и сравнение множества отношений "многие ко многим
Случай: пользователь создает новую заявку. Мне нужно отфильтровать поля (допуски), которые он может выбрать/просмотреть в своей заявке; на основе сравнения следующего:
- пользователи отдел(ы)
- рабочие места пользователей
по сравнению с
- рабочее место (места) отделения
- поля оформления отделов
- рабочее место(я)
мои модели:
class Place(models.Model):
...
name = CICharField(max_length=100)
descr = models.TextField(null=True, blank=True)
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
null=True,blank=True,
related_name='children',
)
#------------------------------
class User(AbstractUser):
....
place = models.ManyToManyField(Place, blank=True, related_name='users')
organization = models.ManyToManyField(Organization, blank=True)
....
#------------------------------
class Organization(models.Model):
...
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
null=True,blank=True,
related_name='children',
)
place = models.ManyToManyField(Place, blank=True)
...
#------------------------------
class Clearance(models.Model):
...
parent = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='clearances')
place = models.ManyToManyField('Place', blank=True, related_name='clearances')
name = models.CharField(max_length=200)
...
#------------------------------
class Requisition(models.Model):
...
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
place = models.ManyToManyField(Place, blank=False, related_name='requisitions')
clearance = models.ManyToManyField(Clearance, blank=True, related_name='requisitions')
...
Пример сценария:
- пользователь является членом только 1 отдела: "Tech dpt" .
- пользователь находится в "Лондоне" и "Эдинбурге"
- Tech dpt находится в "Лондоне", "Эдинбурге" и "Глазго"
Допуск для "Tech dpt" составляет
- C1: Лондон
- C2: Глазго
- C3: Лондон и Эдинбург
- C4: Эдинбург
- C5: Лондон, Эдинбург и Глазго
самым близким запросом, который мне удается выполнить, является следующий:
users_clearances = (
Clearance.objects
#fetch all clearances attached to users org_units
.filter(parent__in=user.organization.all())
#where clearance place is also in users places
.filter(place__in=user.place.all())
поскольку пользователь является членом только "Лондона" и "Эдинбурга", запрос должен вернуть C1, C3 и C4.
Однако, он также возвращает C5.
Поскольку C5 связан с "Лондоном", "Эдинбургом" и "Глазго", он соответствует пользователям "Лондона" и "Эдинбурга"... но я хочу, чтобы он не был присоединен, поскольку у пользователя нет принадлежности в "Глазго"