Есть ли в 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-а?