1

默认情况下,石墨烯附带的relay.ConnectionField实现不会对查询进行分页。(可以选择使用“first”或“last”对连接进行分页。)如果连接具有大量节点,则这是不切实际的。一次强制分页不超过 100 个节点的合适方法是什么?

4

2 回答 2

3

不幸的是,石墨烯不支持默认值。我为这种情况建立了自己的装饰器。设置DEFAULT_PAGE_SIZEMAX_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]
于 2018-01-19T16:25:41.527 回答
1

对于那些寻找 django 解决方案的人,graphene-django 有RELAY_CONNECTION_ENFORCE_FIRST_OR_LASTRELAY_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在 Query 声明中使用。

例如:

# 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")
于 2021-05-17T22:03:24.947 回答