Использование пользовательских подключений в graphene_django

У меня есть вариант проблемы, описанный здесь:

Использование DjangoFilterConnectionField с пользовательским подключением в graphene_django

Измененная проблема заключается в следующем: Допустим, у меня есть класс модели Django 'User', в котором есть поле 'email_addrs', представляющее собой строку адресов электронной почты, разделенных запятыми:

class User(models.Model):
  email_addrs = models.TextField(max_length=512, null=True,
         help_text="Comma-delimited string of email addresses")
  ...<other-fields>...

И у меня есть UserNode(DjangoObjectType), созданный поверх этой модели, с "производным" полем под названием "count_email_addresses" с распознавателем:

class UserNode(DjangoObjectType):
    class Meta:
        model = User
        filter_fields = ('email_addrs', )
        interfaces = (Node, )
        connection = UserConnection
    
    count_email_addresses = graphene.Int()

    @static_method
    resolve_count_email_addresses(parent, info):
       # code to resolve the count of email addresses

Обратите внимание на класс UserConnection (приведенный выше, привязанный к мета-полю "connection"), который я опишу далее. Поле count_email_addesses вернет количество адресов электронной почты для "пользователя". Мое требование - вернуть количество пользователей и общее количество адресов электронной почты у этих пользователей, что является совокупностью для всех пользователей в моем запросе. Для этого я использую класс UserConnection, который определяется как:

class UserConnection(Connection):
    class Meta:
        abstract = True

    count_users = graphene.Int()
    aggregate_count_email_addrs = graphene.Int()

Мне нужно написать распознаватели для 'count_users' и 'aggregate_count_email_addrs'. Распознаватель для count_users прост в использовании и выглядит следующим образом:

   @staticmethod
    def resolve_count_users(root, _info, **kwargs):
        return root.length

И это работает нормально. Аргумент 'root' содержит объекты модели 'User', а распознаватель возвращает их длину. Обратите внимание, что 'root' содержит объекты модели 'User', а не объекты UserNode. Но это прекрасно работает, так как существует взаимно однозначное соответствие между 'User' и 'UserNode', поэтому подсчет идет нормально.

Проблема заключается в распознавателе 'aggregate_count_email_addrs'. Когда я пишу аналогичный распознаватель, поскольку поле "count_email_addresses" находится в UserNode, а не в модели "User", у меня нет доступа к этому полю для выполнения агрегации по всем пользователям.

Я уверен, что это решаемая проблема, просто я ее еще не обнаружил. Буду признателен за любую помощь в ее решении.

Вы могли бы перейти к root.iterable и выполнить требуемую логику

def resolve_aggregate_count_email_addrs(root, _info, **kwargs):
        total = 0
        for user in root.iterable:
            if user.email_addrs:
                total += len([e for e in user.email_addrs.split(",") if e.strip()])
        return total

Но это может оказаться не очень эффективным, и вам, возможно, придется скорректировать свой запрос, чтобы выполнить более оптимизированный набор запросов поверх root.iterable.

Пример:

root.iterable.filter(..).annotate(...)

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