Использование параметров во вложенных полях в graphene-django без реле для целей пагинации
Я использую graphene с django и пытаюсь сделать что-то, что в моей голове должно быть очень просто, но я не нахожу документального подтверждения этому нигде в документации по graphene или на github, а также не видел похожего вопроса здесь. Самое близкое к этому, что я нашел, это: https://www.howtographql.com/graphql-python/8-pagination/, но, как вы видите, мне придется объявить параметры в родительском резольвере, чего я не хочу.
У меня такой запрос
getUser(id: $userIdTarget) {
id
username
trainings{
id
name
sessions{
id
name
}
}
}
}
Я хотел бы реализовать пагинацию в подполе сессий. Вот что я хотел бы получить:
getUser(id: $userIdTarget) {
id
username
trainings{
id
name
sessions(first:10){
id
name
}
}
}
}
а в резольвере я бы реализовал что-то вроде этого:
def resolve_sessions(root, info, first=None, skip=None):
if skip:
return gql_optimizer.query(Session.objects.all().order_by('-id')[skip:], info)
elif first:
return gql_optimizer.query(Session.objects.all().order_by('-id')[:first], info)
else:
return gql_optimizer.query(Session.objects.all().order_by('-id'), info)
(gql_optimizer - это просто библиотека-обертка оптимизации, которую я использую)
Однако это не работает, поскольку поле sessions соответствует списку модели Session, которая является fk to Training согласно моим моделям django, так что это автоматически разрешается graphene, поскольку эти типы являются DjangoObjectType, поэтому я не совсем уверен, как можно настроить эти резольверы (и возможно ли это вообще).
Ниже я оставлю соответствующие модели и типы:
Модель сессии
class Session(models.Model):
name = models.CharField(max_length=200, help_text='Session\'s name')
category = models.CharField(max_length=240, choices=SESSION_CATEGORIES, default="practice",
help_text='Session type. Can be of \'assessment\''
'or \'practice\'')
total_steps = models.IntegerField(default=1, help_text='Amount of steps for this session')
created_at = models.DateTimeField(editable=False, default=timezone.now, help_text='Time the session was created'
'(Optional - default=now)')
completed_at = models.DateTimeField(editable=False, null=True, blank=True, help_text='Time the session was finished'
'(Optional - default=null)')
is_complete = models.BooleanField(default=0)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="training_sessions", on_delete=models.DO_NOTHING)
training = models.ForeignKey("Training", related_name="sessions", on_delete=models.CASCADE)
def __str__(self):
return self.name
UserType
class UserType(DjangoObjectType):
class Meta:
model = get_user_model()
fields = "__all__"
@classmethod
def get_queryset(cls, queryset, info, **kwargs):
if info.variable_values.get('orgId') and info.variable_values.get('orgId') is not None:
return queryset.order_by('username')
return queryset
SessionType
class SessionType(DjangoObjectType):
class Meta:
model = Session
fields = "__all__"
convert_choices_to_enum = False
@classmethod
def get_queryset(cls, queryset, info, **kwargs):
if info.variable_values.get('userId') and info.variable_values.get('userId') is not None:
return queryset.filter(Q(user_id=info.variable_values.get('userId'))).order_by('-id')
return queryset
TrainingType
class TrainingType(gql_optimizer.OptimizedDjangoObjectType):
class Meta:
model = Training
fields = "__all__"
convert_choices_to_enum = False
Можно расширить типы, чтобы добавить дополнительные поля, которых нет в модели Django - возможно, это та техника, которую вы ищете, чтобы ввести больше данных в запрос?
class TrainingType(gql_optimizer.OptimizedDjangoObjectType):
my_extra_field = graphene.Int() # for example
class Meta:
model = Training
fields = "__all__"
convert_choices_to_enum = False
Вы также можете переопределить резольверы по умолчанию, которые создаются с помощью DjangoObjectType
.