Запрос Django Q-Object возвращает дубликаты записей, не соответствующие базе данных

Я пытаюсь определить принадлежность пользователя к событию (организационная структура высшего уровня в моем приложении). Каждое событие содержит пользователей с одним (и только одним) из трех уровней доступа (менеджер, редактор или наблюдатель). В любой момент времени должен быть хотя бы один manager, по умолчанию это создатель события. Я использую контекстный процессор для запроса БД на любые события, к которым имеет доступ мой активный пользователь (через одну из трех ролей). Это должно вернуть список всех соответствующих event объектов.
Моя проблема заключается в том, что когда я добавляю в event хотя бы двух дополнительных пользователей другой роли, в списке events для моего пользователя появляются дублирующие записи для этого event (по одной на дополнительную роль и по две на дополнительного пользователя в этой роли помимо первого пользователя). Это означает, что если я добавлю двух редакторов, я увижу две записи для события. Добавив еще двух наблюдателей, я увижу четыре записи, добавив третьего наблюдателя, я увижу шесть записей. Добавление только одного наблюдателя или редактора или любого количества дополнительных менеджеров (когда мой собственный активный пользователь является менеджером) не приведет к появлению дубликатов.
Записи в БД и SQL-запросы выглядят корректно, и при запросе фильтрации членства только для одной роли за раз, результаты тоже корректны. Только при объединении запросов Q-объектов через OR возникает странное поведение.
. (На данный момент я обошел эту проблему, используя .distinct() в запросе, но это не решает основную проблему.)

Может ли кто-нибудь объяснить мне, что я упускаю? Код ниже, включая некоторые из моих отладочных отпечатков и логику управления ролями для профилей пользователей (хотя это, кажется, работает нормально, судя по содержимому БД) для полноты картины.

Я использую Python 3.9, Django 3.2.5 и SQLite 3.31.1

context_processor.py (без .distinct(); User is manager)

from base.models import *
from django.db.models import Q

def eventlist(request):
    args = {}
    if request.user.id is not None and request.user.id > 0:
        print(request.user.profile)
        query = (Q(event_observer=request.user.profile) | Q(event_editor=request.user.profile) | Q(event_manager=request.user.profile)) #returns duplicates of an event if more than one editor/observer each exist in it, NOT expected
        user_events = Event.objects.filter(query)
        args.update({"user_events": user_events})
        print(user_events)
        print(Event.objects.filter(Q(event_observer=request.user.profile))) #returns nothing, as expected
        print(Event.objects.filter(Q(event_editor=request.user.profile))) #returns nothing, as expected
        print(Event.objects.filter(Q(event_manager=request.user.profile))) #returns all proper events, as expected
        print(Event.objects.filter(Q(event_manager=request.user.profile) | Q(event_editor=request.user.profile))) #returns duplicates of an event if more than one editor exists in it, NOT expected
        print(Event.objects.filter(Q(event_observer=request.user.profile) | Q(event_editor=request.user.profile))) #returns nothing, as expected
    return args

base/models.py (События)

import hashlib
from django.db import models
from django.template.defaultfilters import slugify
from base.utils import get_or_none
from django.contrib.auth.models import User

class Event(models.Model):
    slug = models.SlugField(max_length=10, default=None)
    name = models.CharField(verbose_name="Name", unique=True, max_length=50)
    prefix = models.CharField(verbose_name="Prefix (for data entries)", unique=True, max_length=8)
    date = models.DateField(verbose_name="Starting Date (DD.MM.YYYY)")
    description = models.TextField(verbose_name="Description")

    def __str__(self):
        return str(self.name)

(... some stuff relating to creating unique slugs and names for new events...)

accounts/models.py (Профили пользователей)

from django.db import models
from django.contrib.auth.models import User
from base.models import Event
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, related_name="profile", on_delete=models.CASCADE)
    is_observer = models.ManyToManyField(Event, related_name="event_observer", blank=True)
    is_editor = models.ManyToManyField(Event, related_name="event_editor", blank=True)
    is_manager = models.ManyToManyField(Event, related_name="event_manager", blank=True)

    def __str__(self):
        return self.user.username

    def get_permission(self, event):
        print('Observer:', self.is_observer.all())
        print('Editor:', self.is_editor.all())
        print('Manager:', self.is_manager.all())
        print()
        print(self.is_observer.filter(id=event))
        print(self.is_editor.filter(id=event))
        print(self.is_manager.filter(id=event))

        if self.is_observer.filter(id=event).exists():
            return 'observer'
        elif self.is_editor.filter(id=event).exists():
            return 'editor'
        elif self.is_manager.filter(id=event).exists():
            return 'manager'
        else:
            return None

    def change_permissions(self, event, level):
        if level == "observer":
            self.is_observer.add(event)
            self.is_editor.remove(event)
            self.is_manager.remove(event)
        elif level == "editor":
            self.is_observer.remove(event)
            self.is_editor.add(event)
            self.is_manager.remove(event)
        elif level == "manager":
            self.is_observer.remove(event)
            self.is_editor.remove(event)
            self.is_manager.add(event)
        elif level == "remove":
            self.is_observer.remove(event)
            self.is_editor.remove(event)
            self.is_manager.remove(event)
        else:
            return 1
        return 0

    def set_observer(self, event):
        return self.change_permissions(event, "observer")

    def set_editor(self, event):
        return self.change_permissions(event, "editor")

    def set_manager(self, event):
        return self.change_permissions(event, "manager")

    def remove_from_event(self, event):
        return self.change_permissions(event, "remove")


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()
Вернуться на верх