LoginSignup
1

More than 5 years have passed since last update.

graphene-djangoで一度に取得できる件数を制限する

Last updated at Posted at 2018-05-26

背景

graphene-django は簡単に取得件数を制限(SQLでいうlimit)できるようになっておらず、全件取得できてしまう。
そこで1回のクエリで取得できる件数の制限を行えるようにする。

動作環境

  • Python3
  • django 2.0.1
  • graphene-django 2.0.0
  • django-filter 1.1.0

コード

基本方針はDjangoFilterConnectionFieldを継承した独自のFilterConnectionを実装し、検索件数を制限すること。今回は1回のアクセスで最大1000件までとする。

models.py
from django.db import models

## 対象のモデル. なんでも大丈夫
class Tags(models.Model):
    name = models.CharField(max_length=128, blank=True, null=True)
    description = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'tags'
schema.py
from graphene import Schema, ObjectType, Node
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from . import models

# connection_resolverをオーバーライドし最大件数を指定する
class LimitedDjangoFilterConnectionField(DjangoFilterConnectionField):

    # 今回は一度に取得できる最大件数を1000とする
    MAX_LIMIT = 1000

    @classmethod
    def connection_resolver(cls,
        resolver,
        connection,
        default_manager,
        max_limit, #1回で取得できる最大件数
        enforce_first_or_last, #firstかlastが必要とするかどうか
        filterset_class,
        filtering_args,
        root,
        info,
        **args):

        return super(LimitedDjangoFilterConnectionField, cls).connection_resolver(
            resolver,
            connection,
            default_manager,
            MAX_LIMIT, #ここで1回に取得できる最大件数を指定
            True, #ここでfirstかlastを必要とするように指定
            filterset_class,
            filtering_args,
            root,
            info,
            **args)

class Tag(DjangoObjectType):
    class Meta:
        model = models.Tags
        interfaces = (Node, )
        filter_fields = {
            "name": ["icontains"],
            "description": ["icontains"]
        }

class Query(ObjectType):
    tag =  Node.Field(Tag)
    # 上で定義した独自クラスを使用
    all_tags =  LimitedDjangoFilterConnectionField(tag)

schema = Schema(query=Query)

クエリ例

下記クエリを投げるとエラーが返される。

# 指定件数が多すぎる場合
query {
  allTags(first: 2000) {
    edges {
      node {
        name
      }
    }
  }
}
# 指定件数がない場合
query {
  allTags(name_Icontains: "Py") {
    edges {
      node {
        name
      }
    }
  }
}

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1