在没有中继的情况下使用带有graphene-django的子字段中的参数进行分页
Posted
技术标签:
【中文标题】在没有中继的情况下使用带有graphene-django的子字段中的参数进行分页【英文标题】:Use parameters in subfields with graphene-django without relay for pagination purpose 【发布时间】:2022-01-08 00:42:33 【问题描述】:我正在将石墨烯与 django 一起使用,我正在努力做一些我认为应该非常简单的事情,但我没有发现它在石墨烯文档或 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 只是我使用的一个优化包装库)
但是这不起作用,因为字段会话对应于模型 Session 的列表,该列表是根据我的 django 模型进行训练的 fk,因此石墨烯会自动解决此问题,因为这些类型是 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
用户类型
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
会话类型
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
培训类型
class TrainingType(gql_optimizer.OptimizedDjangoObjectType):
class Meta:
model = Training
fields = "__all__"
convert_choices_to_enum = False
【问题讨论】:
【参考方案1】:可以扩展您的类型以添加更多不在 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
创建的默认解析器。
【讨论】:
我将其标记为正确答案,并在我阅读时表示赞成,这一切都是有道理的,似乎是答案。今天我有机会尝试,不幸的是它并没有解决问题。这不适用于从外键关系自动创建的子字段 您还可以将对象添加为附加字段,然后进一步扩展您的自定义解析以填充这些字段。以上是关于在没有中继的情况下使用带有graphene-django的子字段中的参数进行分页的主要内容,如果未能解决你的问题,请参考以下文章