Есть ли в Django нативный способ вызвать RelatedManager у QuerySet-а?

Есть три модэли.
User - модэль пользователя из django.contrib.auth.models.
Role - список возможных ролей.

И есть модэль соеденяющая первые две через many_to_one отношения к себе.

Django умеет генерировать RelatedManager у связанных модэлей.
То есть у User и Role появляется параметр userrole_set который возвращает QuerySet связанных обьектов к одному конкретному.

class User(Model):
    name = CharField(max_length=100)


class Role(Model):
    name = CharField(max_length=100)


class UserRole(Model):
    user = ForeignKey(to=User, on_delete=CASCADE)
    role = ForeignKey(to=Role, on_delete=CASCADE)
    # other fields

Задача состоит в том чтобы достать все роли конкретного юзера, и всех юзеров с конкретной ролью, самым коротким путём.

Есть такое решение.

userrole_ids = user.userrole_set.values_list('id', flat=True)
role_set = Role.objects.filter(id__in=userrole_ids)

Но если добавить ещё пару связей то такой код будет разростаться и повторятся в разных местах.

Я ищу что-то в одну строку вроде:

role_set = user.userrole_set.role_set

Есть второй вариант через добавление метода к модэли:

class User(Model):
    name = CharField(max_length=100)

    def role_set(self):
        return Role.objects.filter(id__in=self.userrole_set.values_list('id', flat=True))

role_set = user.role_set()

Но он тоже не очень, так как:
а) для обратной связи нужен второй метод у Role (достать всех пользователей с конкретной ролю).
б) в реальных проектах сотни модэлей и для кождой второй связи писать велосипед не очень хочется.

Есть третий вариант - поменять тип отношения и сами модэли:

class User(Model):
    name = CharField(max_length=100)
    role_set = ManyToManyField(to=Role)

Но и он не подходит так как у связующей модели могут быть дополнительные поля (кем и когда была назначенна роль итд.).

Вопрос таков: Есть ли в Django нативный способ вызвать RelatedManager у QuerySet-а?


Ответы (0 шт):