Использование параметров во вложенных полях в 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.

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