Использование пользовательских подключений в 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(...)