【发布时间】:2017-09-25 14:09:47
【问题描述】:
默认情况下,石墨烯附带的relay.ConnectionField 实现不会对查询进行分页。 (可以选择使用“first”或“last”对连接进行分页。)如果连接具有大量节点,则这是不切实际的。什么是强制分页的合适方法,例如一次不超过 100 个节点?
【问题讨论】:
-
什么意思?你想在实际查询中询问接下来的两个吗?
标签: pagination graphene-python
默认情况下,石墨烯附带的relay.ConnectionField 实现不会对查询进行分页。 (可以选择使用“first”或“last”对连接进行分页。)如果连接具有大量节点,则这是不切实际的。什么是强制分页的合适方法,例如一次不超过 100 个节点?
【问题讨论】:
标签: pagination graphene-python
不幸的是,Graphene 不支持默认值。我为这种情况建立了自己的装饰器。适当设置DEFAULT_PAGE_SIZE 和MAX_PAGE_SIZE。也可以调整为从装饰器本身接收这些值,但我将它与 Django 和 ergo Django 的设置一起使用。
DEFAULT_PAGE_SIZE = 10
MAX_PAGE_SIZE = 100
def limited_pagination(func):
'''
Decorator for limiting the `first` and `last` pagination parameters. Uses
DEFAULT_PAGE_SIZE and MAX_PAGE_SIZE settings. Raises an exception when
values are invalid.
'''
def wrapper(*args, **kwargs):
if 'first' in kwargs and 'last' in kwargs:
raise RuntimeError('Use either `first` or `last`, not both.')
for key in ('first', 'last'):
if key in kwargs:
try:
value = int(kwargs[key])
except ValueError:
raise ValueError('`{}` must be an integer.'.format(key))
if value < 0:
raise ValueError('`{}` must be 0 or greater.'.format(key))
elif value > MAX_PAGE_SIZE:
raise ValueError(
'`{}` must not be greater than {}.'.format(
key, MAX_PAGE_SIZE
)
)
kwargs[key] = value
break # Break out of for loop to skip `else` branch.
else:
kwargs['first'] = DEFAULT_PAGE_SIZE
result = func(*args, **kwargs)
return result
return wrapper
使用示例:
@limited_pagination
def resolve_whatever(self, info):
return [1, 2, 3, 4, 5]
【讨论】:
对于那些寻找 django 解决方案的人,graphene-django 有 RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST 和 RELAY_CONNECTION_MAX_LIMIT 设置:https://docs.graphene-python.org/projects/django/en/latest/settings/#relay-connection-enforce-first-or-last。您只需要启用RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST,并确保在查询声明中使用DjangoConnectionField。
例如:
# settings
GRAPHENE = {
'RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST': True,
'RELAY_CONNECTION_MAX_LIMIT': 50,
}
# model
class Category(models.Model):
name = models.CharField(max_length=100)
# graphql type
class CategoryType(graphene_django.DjangoObjectType):
class Meta:
model = Category
fields = ("id", 'name')
interfaces = (graphene.relay.Node,)
# query
class Query(graphene.ObjectType):
categories = graphene_django.DjangoConnectionField(CategoryType)
def resolve_categories(root, info, **kwargs):
return Category.objects.all().order_by("id")
【讨论】: