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 связан с "Лондоном", "Эдинбургом" и "Глазго", он соответствует пользователям "Лондона" и "Эдинбурга"... но я хочу, чтобы он не был присоединен, поскольку у пользователя нет принадлежности в "Глазго"

Вернуться на верх