graphene-django-filter


Namegraphene-django-filter JSON
Version 0.6.5 PyPI version JSON
download
home_pagehttps://github.com/devind-team/graphene-django-filter
SummaryAdvanced filters for Graphene
upload_time2023-06-10 10:28:50
maintainer
docs_urlNone
authordevind-team
requires_python>=3.8,<4.0
licenseMIT
keywords django graphene filter
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # Graphene-Django-Filter
[![CI](https://github.com/devind-team/graphene-django-filter/workflows/CI/badge.svg)](https://github.com/devind-team/graphene-django-filter/actions)
[![Coverage Status](https://coveralls.io/repos/github/devind-team/graphene-django-filter/badge.svg?branch=main)](https://coveralls.io/github/devind-team/graphene-django-filter?branch=main)
[![PyPI version](https://badge.fury.io/py/graphene-django-filter.svg)](https://badge.fury.io/py/graphene-django-filter)
[![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/licenses/MIT)

This package contains advanced filters for [graphene-django](https://github.com/graphql-python/graphene-django).
The standard filtering feature in graphene-django relies on the [django-filter](https://github.com/carltongibson/django-filter)
library and therefore provides the flat API without the ability to use logical operators such as
`and`, `or` and `not`. This library makes the API nested and adds logical expressions by extension
of the `DjangoFilterConnectionField` field and the `FilterSet` class.
Also, the library provides some other convenient filtering features.

# Installation
```shell
# pip
pip install graphene-django-filter
# poetry
poetry add graphene-django-filter
```

# Requirements
* Python (3.7, 3.8, 3.9, 3.10)
* Graphene-Django (2.15)

# Features

## Nested API with the ability to use logical operators
To use, simply replace all `DjangoFilterConnectionField` fields with
`AdvancedDjangoFilterConnectionField` fields in your queries.
Also,if you create custom FilterSets, replace the inheritance from the `FilterSet` class
with the inheritance from the `AdvancedFilterSet` class.
For example, the following task query exposes the old flat API.
```python
import graphene
from django_filters import FilterSet
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField

class TaskFilter(FilterSet):
    class Meta:
        model = Task
        fields = {
            'name': ('exact', 'contains'),
            'user__email': ('exact', 'contains'),
            'user__first_name': ('exact', 'contains'),
            'user__last_name': ('exact', 'contains'),
        }

class UserType(DjangoObjectType):
    class Meta:
        model = User
        interfaces = (graphene.relay.Node,)
        fields = '__all__'

class TaskType(DjangoObjectType):
    user = graphene.Field(UserType)

    class Meta:
        model = Task
        interfaces = (graphene.relay.Node,)
        fields = '__all__'
        filterset_class = TaskFilter

class Query(graphene.ObjectType):
    tasks = DjangoFilterConnectionField(TaskType)
```
The flat API in which all filters are applied using the `and` operator looks like this.
```graphql
{
  tasks(
    name_Contains: "important"
    user_Email_Contains: "john"
    user_FirstName: "John"
    user_LastName: "Dou"
  ){
    edges {
      node {
        id
        name
      }
    }
  }
}
```
After replacing the field class with the `AdvancedDjangoFilterConnectionField`
and the `FilterSet` class with the `AdvancedFilterSet`
the API becomes nested with support for logical expressions.
```python
import graphene
from graphene_django_filter import AdvancedDjangoFilterConnectionField, AdvancedFilterSet

class TaskFilter(AdvancedFilterSet):
    class Meta:
        model = Task
        fields = {
            'name': ('exact', 'contains'),
            'user__email': ('exact', 'contains'),
            'user__first_name': ('exact', 'contains'),
            'user__last_name': ('exact', 'contains'),
        }

class Query(graphene.ObjectType):
    tasks = AdvancedDjangoFilterConnectionField(TaskType)
```
For example, the following query returns tasks which names contain the word "important"
or the user's email address contains the word "john" and the user's last name is "Dou"
and the first name is not "John".
Note that the operators are applied to lookups
such as `contains`, `exact`, etc. at the last level of nesting.
```graphql
{
  tasks(
    filter: {
      or: [
        {name: {contains: "important"}}
        {
            and: [
              {user: {email: {contains: "john"}}}
              {user: {lastName: {exact: "Dou"}}}
            ]
        }
      ]
      not: {
        user: {firstName: {exact: "John"}}
      }
    }
  ) {
    edges {
      node {
        id
        name
      }
    }
  }
}
```
The same result can be achieved with an alternative query structure
because within the same object the `and` operator is always used.
```graphql
{
  tasks(
    filter: {
      or: [
        {name: {contains: "important"}}
        {
          user: {
            email: {contains: "john"}
            lastName: {exact: "Dou"}
          }
        }
      ]
      not: {
        user: {firstName: {exact: "John"}}
      }
    }
  ){
    edges {
      node {
        id
        name
      }
    }
  }
}
```
The filter input type has the following structure.
```graphql
input FilterInputType {
  and: [FilterInputType]
  or: [FilterInputType]
  not: FilterInputType
  ...FieldLookups
}
```
For more examples, see [tests](https://github.com/devind-team/graphene-django-filter/blob/06ed0af8def8a4378b4c65a5d137ef17b6176cab/tests/test_queries_execution.py#L23).

## Full text search
Django provides the [API](https://docs.djangoproject.com/en/3.2/ref/contrib/postgres/search/)
for PostgreSQL full text search. Graphene-Django-Filter inject this API into the GraphQL filter API.
To use, add `full_text_search` lookup to fields for which you want to enable full text search.
For example, the following type has full text search for
`first_name` and `last_name` fields.
```python
import graphene
from graphene_django import DjangoObjectType
from graphene_django_filter import AdvancedDjangoFilterConnectionField

class UserType(DjangoObjectType):
    class Meta:
        model = User
        interfaces = (graphene.relay.Node,)
        fields = '__all__'
        filter_fields = {
            'email': ('exact', 'startswith', 'contains'),
            'first_name': ('exact', 'contains', 'full_text_search'),
            'last_name': ('exact', 'contains', 'full_text_search'),
        }

class Query(graphene.ObjectType):
    users = AdvancedDjangoFilterConnectionField(UserType)
```
Since this feature belongs to the AdvancedFilterSet,
it can be used in a custom FilterSet.
The following example will work exactly like the previous one.
```python
import graphene
from graphene_django import DjangoObjectType
from graphene_django_filter import AdvancedDjangoFilterConnectionField, AdvancedFilterSet

class UserFilter(AdvancedFilterSet):
    class Meta:
        model = User
        fields = {
            'email': ('exact', 'startswith', 'contains'),
            'first_name': ('exact', 'contains', 'full_text_search'),
            'last_name': ('exact', 'contains', 'full_text_search'),
        }

class UserType(DjangoObjectType):
    class Meta:
        model = User
        interfaces = (graphene.relay.Node,)
        fields = '__all__'
        filterset_class = UserFilter

class Query(graphene.ObjectType):
    users = AdvancedDjangoFilterConnectionField(UserType)
```
Full text search API includes SearchQuery, SearchRank, and Trigram filters.
SearchQuery and SearchRank filters are at the top level.
If some field has been enabled for full text search then it can be included in the field array.
The following queries show an example of using the SearchQuery and SearchRank filters.
```graphql
{
  users(
    filter: {
      searchQuery: {
        vector: {
          fields: ["first_name"]
        }
        query: {
          or: [
            {value: "Bob"}
            {value: "Alice"}
          ]
        }
      }
    }
  ){
    edges {
      node {
        id
        firstName
        lastName  
      }
    }
  }
}
```
```graphql
{
  users(
    filter: {
      searchRank: {
        vector: {fields: ["first_name", "last_name"]}
        query: {value: "John Dou"}
        lookups: {gte: 0.5}
      }
    }
  ){
    edges {
      node {
        id
        firstName
        lastName  
      }
    }
  }
}
```
Trigram filter belongs to the corresponding field.
The following query shows an example of using the Trigram filter.
```graphql
{
  users(
    filter: {
      firstName: {
        trigram: {
          value: "john"
          lookups: {gte: 0.85}
        }
      }
    }
  ){
    edges {
      node {
        id
        firstName
        lastName  
      }
    }
  }
}
```
Input types have the following structure.
```graphql
input SearchConfigInputType {
  value: String!
  isField: Boolean
}
enum SearchVectorWeight {
  A
  B
  C
  D
}
input SearchVectorInputType {
  fields: [String!]!
  config: SearchConfigInputType
  weight: SearchVectorWeight
}
enum SearchQueryType {
  PLAIN
  PHRASE
  RAW
  WEBSEARCH
}
input SearchQueryInputType {
  value: String
  config: SearchConfigInputType
  and: [SearchQueryInputType]
  or: [SearchQueryInputType]
  not: SearchQueryInputType
}
input SearchQueryFilterInputType {
  vector: SearchVectorInputType!
  query: SearchQueryInputType!
}
input FloatLookupsInputType {
  exact: Float
  gt: Float
  gte: Float
  lt: Float
  lte: Float
}
input SearchRankWeightsInputType {
  D: Float
  C: Float
  B: Float
  A: Float
}
input SearchRankFilterInputType {
  vector: SearchVectorInputType!
  query: SearchQueryInputType!
  lookups: FloatLookupsInputType!
  weights: SearchRankWeightsInputType
  coverDensity: Boolean
  normalization: Int
}
enum TrigramSearchKind {
  SIMILARITY
  DISTANCE
}
input TrigramFilterInputType {
  kind: TrigramSearchKind
  lookups: FloatLookupsInputType!
  value: String!
}
```
For more examples, see [tests](https://github.com/devind-team/graphene-django-filter/blob/06ed0af8def8a4378b4c65a5d137ef17b6176cab/tests/test_queries_execution.py#L134).

## Settings
The library can be customised using settings.
To add settings, create a dictionary
with name `GRAPHENE_DJANGO_FILTER` in the project’s `settings.py`.
The default settings are as follows.
```python
GRAPHENE_DJANGO_FILTER = {
    'FILTER_KEY': 'filter',
    'AND_KEY': 'and',
    'OR_KEY': 'or',
    'NOT_KEY': 'not',
}
```
To read the settings, import them from the `conf` module.
```python
from graphene_django_filter.conf import settings

print(settings.FILTER_KEY)
```
The `settings` object also includes fixed settings, which depend on the user's environment.
`IS_POSTGRESQL` determinate that current database is PostgreSQL
and `HAS_TRIGRAM_EXTENSION` that `pg_trgm` extension is installed.


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/devind-team/graphene-django-filter",
    "name": "graphene-django-filter",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "django,graphene,filter",
    "author": "devind-team",
    "author_email": "team@devind.ru",
    "download_url": "https://files.pythonhosted.org/packages/c2/44/4d9a9bdf2ad428f61a7a79ec9438eaad01915284b01afabf1b26fb6a9667/graphene_django_filter-0.6.5.tar.gz",
    "platform": null,
    "description": "# Graphene-Django-Filter\n[![CI](https://github.com/devind-team/graphene-django-filter/workflows/CI/badge.svg)](https://github.com/devind-team/graphene-django-filter/actions)\n[![Coverage Status](https://coveralls.io/repos/github/devind-team/graphene-django-filter/badge.svg?branch=main)](https://coveralls.io/github/devind-team/graphene-django-filter?branch=main)\n[![PyPI version](https://badge.fury.io/py/graphene-django-filter.svg)](https://badge.fury.io/py/graphene-django-filter)\n[![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/licenses/MIT)\n\nThis package contains advanced filters for [graphene-django](https://github.com/graphql-python/graphene-django).\nThe standard filtering feature in graphene-django relies on the [django-filter](https://github.com/carltongibson/django-filter)\nlibrary and therefore provides the flat API without the ability to use logical operators such as\n`and`, `or` and `not`. This library makes the API nested and adds logical expressions by extension\nof the `DjangoFilterConnectionField` field and the `FilterSet` class.\nAlso, the library provides some other convenient filtering features.\n\n# Installation\n```shell\n# pip\npip install graphene-django-filter\n# poetry\npoetry add graphene-django-filter\n```\n\n# Requirements\n* Python (3.7, 3.8, 3.9, 3.10)\n* Graphene-Django (2.15)\n\n# Features\n\n## Nested API with the ability to use logical operators\nTo use, simply replace all `DjangoFilterConnectionField` fields with\n`AdvancedDjangoFilterConnectionField` fields in your queries.\nAlso,if you create custom FilterSets, replace the inheritance from the `FilterSet` class\nwith the inheritance from the `AdvancedFilterSet` class.\nFor example, the following task query exposes the old flat API.\n```python\nimport graphene\nfrom django_filters import FilterSet\nfrom graphene_django import DjangoObjectType\nfrom graphene_django.filter import DjangoFilterConnectionField\n\nclass TaskFilter(FilterSet):\n    class Meta:\n        model = Task\n        fields = {\n            'name': ('exact', 'contains'),\n            'user__email': ('exact', 'contains'),\n            'user__first_name': ('exact', 'contains'),\n            'user__last_name': ('exact', 'contains'),\n        }\n\nclass UserType(DjangoObjectType):\n    class Meta:\n        model = User\n        interfaces = (graphene.relay.Node,)\n        fields = '__all__'\n\nclass TaskType(DjangoObjectType):\n    user = graphene.Field(UserType)\n\n    class Meta:\n        model = Task\n        interfaces = (graphene.relay.Node,)\n        fields = '__all__'\n        filterset_class = TaskFilter\n\nclass Query(graphene.ObjectType):\n    tasks = DjangoFilterConnectionField(TaskType)\n```\nThe flat API in which all filters are applied using the `and` operator looks like this.\n```graphql\n{\n  tasks(\n    name_Contains: \"important\"\n    user_Email_Contains: \"john\"\n    user_FirstName: \"John\"\n    user_LastName: \"Dou\"\n  ){\n    edges {\n      node {\n        id\n        name\n      }\n    }\n  }\n}\n```\nAfter replacing the field class with the `AdvancedDjangoFilterConnectionField`\nand the `FilterSet` class with the `AdvancedFilterSet`\nthe API becomes nested with support for logical expressions.\n```python\nimport graphene\nfrom graphene_django_filter import AdvancedDjangoFilterConnectionField, AdvancedFilterSet\n\nclass TaskFilter(AdvancedFilterSet):\n    class Meta:\n        model = Task\n        fields = {\n            'name': ('exact', 'contains'),\n            'user__email': ('exact', 'contains'),\n            'user__first_name': ('exact', 'contains'),\n            'user__last_name': ('exact', 'contains'),\n        }\n\nclass Query(graphene.ObjectType):\n    tasks = AdvancedDjangoFilterConnectionField(TaskType)\n```\nFor example, the following query returns tasks which names contain the word \"important\"\nor the user's email address contains the word \"john\" and the user's last name is \"Dou\"\nand the first name is not \"John\".\nNote that the operators are applied to lookups\nsuch as `contains`, `exact`, etc. at the last level of nesting.\n```graphql\n{\n  tasks(\n    filter: {\n      or: [\n        {name: {contains: \"important\"}}\n        {\n            and: [\n              {user: {email: {contains: \"john\"}}}\n              {user: {lastName: {exact: \"Dou\"}}}\n            ]\n        }\n      ]\n      not: {\n        user: {firstName: {exact: \"John\"}}\n      }\n    }\n  ) {\n    edges {\n      node {\n        id\n        name\n      }\n    }\n  }\n}\n```\nThe same result can be achieved with an alternative query structure\nbecause within the same object the `and` operator is always used.\n```graphql\n{\n  tasks(\n    filter: {\n      or: [\n        {name: {contains: \"important\"}}\n        {\n          user: {\n            email: {contains: \"john\"}\n            lastName: {exact: \"Dou\"}\n          }\n        }\n      ]\n      not: {\n        user: {firstName: {exact: \"John\"}}\n      }\n    }\n  ){\n    edges {\n      node {\n        id\n        name\n      }\n    }\n  }\n}\n```\nThe filter input type has the following structure.\n```graphql\ninput FilterInputType {\n  and: [FilterInputType]\n  or: [FilterInputType]\n  not: FilterInputType\n  ...FieldLookups\n}\n```\nFor more examples, see [tests](https://github.com/devind-team/graphene-django-filter/blob/06ed0af8def8a4378b4c65a5d137ef17b6176cab/tests/test_queries_execution.py#L23).\n\n## Full text search\nDjango provides the [API](https://docs.djangoproject.com/en/3.2/ref/contrib/postgres/search/)\nfor PostgreSQL full text search. Graphene-Django-Filter inject this API into the GraphQL filter API.\nTo use, add `full_text_search` lookup to fields for which you want to enable full text search.\nFor example, the following type has full text search for\n`first_name` and `last_name` fields.\n```python\nimport graphene\nfrom graphene_django import DjangoObjectType\nfrom graphene_django_filter import AdvancedDjangoFilterConnectionField\n\nclass UserType(DjangoObjectType):\n    class Meta:\n        model = User\n        interfaces = (graphene.relay.Node,)\n        fields = '__all__'\n        filter_fields = {\n            'email': ('exact', 'startswith', 'contains'),\n            'first_name': ('exact', 'contains', 'full_text_search'),\n            'last_name': ('exact', 'contains', 'full_text_search'),\n        }\n\nclass Query(graphene.ObjectType):\n    users = AdvancedDjangoFilterConnectionField(UserType)\n```\nSince this feature belongs to the AdvancedFilterSet,\nit can be used in a custom FilterSet.\nThe following example will work exactly like the previous one.\n```python\nimport graphene\nfrom graphene_django import DjangoObjectType\nfrom graphene_django_filter import AdvancedDjangoFilterConnectionField, AdvancedFilterSet\n\nclass UserFilter(AdvancedFilterSet):\n    class Meta:\n        model = User\n        fields = {\n            'email': ('exact', 'startswith', 'contains'),\n            'first_name': ('exact', 'contains', 'full_text_search'),\n            'last_name': ('exact', 'contains', 'full_text_search'),\n        }\n\nclass UserType(DjangoObjectType):\n    class Meta:\n        model = User\n        interfaces = (graphene.relay.Node,)\n        fields = '__all__'\n        filterset_class = UserFilter\n\nclass Query(graphene.ObjectType):\n    users = AdvancedDjangoFilterConnectionField(UserType)\n```\nFull text search API includes SearchQuery, SearchRank, and Trigram filters.\nSearchQuery and SearchRank filters are at the top level.\nIf some field has been enabled for full text search then it can be included in the field array.\nThe following queries show an example of using the SearchQuery and SearchRank filters.\n```graphql\n{\n  users(\n    filter: {\n      searchQuery: {\n        vector: {\n          fields: [\"first_name\"]\n        }\n        query: {\n          or: [\n            {value: \"Bob\"}\n            {value: \"Alice\"}\n          ]\n        }\n      }\n    }\n  ){\n    edges {\n      node {\n        id\n        firstName\n        lastName  \n      }\n    }\n  }\n}\n```\n```graphql\n{\n  users(\n    filter: {\n      searchRank: {\n        vector: {fields: [\"first_name\", \"last_name\"]}\n        query: {value: \"John Dou\"}\n        lookups: {gte: 0.5}\n      }\n    }\n  ){\n    edges {\n      node {\n        id\n        firstName\n        lastName  \n      }\n    }\n  }\n}\n```\nTrigram filter belongs to the corresponding field.\nThe following query shows an example of using the Trigram filter.\n```graphql\n{\n  users(\n    filter: {\n      firstName: {\n        trigram: {\n          value: \"john\"\n          lookups: {gte: 0.85}\n        }\n      }\n    }\n  ){\n    edges {\n      node {\n        id\n        firstName\n        lastName  \n      }\n    }\n  }\n}\n```\nInput types have the following structure.\n```graphql\ninput SearchConfigInputType {\n  value: String!\n  isField: Boolean\n}\nenum SearchVectorWeight {\n  A\n  B\n  C\n  D\n}\ninput SearchVectorInputType {\n  fields: [String!]!\n  config: SearchConfigInputType\n  weight: SearchVectorWeight\n}\nenum SearchQueryType {\n  PLAIN\n  PHRASE\n  RAW\n  WEBSEARCH\n}\ninput SearchQueryInputType {\n  value: String\n  config: SearchConfigInputType\n  and: [SearchQueryInputType]\n  or: [SearchQueryInputType]\n  not: SearchQueryInputType\n}\ninput SearchQueryFilterInputType {\n  vector: SearchVectorInputType!\n  query: SearchQueryInputType!\n}\ninput FloatLookupsInputType {\n  exact: Float\n  gt: Float\n  gte: Float\n  lt: Float\n  lte: Float\n}\ninput SearchRankWeightsInputType {\n  D: Float\n  C: Float\n  B: Float\n  A: Float\n}\ninput SearchRankFilterInputType {\n  vector: SearchVectorInputType!\n  query: SearchQueryInputType!\n  lookups: FloatLookupsInputType!\n  weights: SearchRankWeightsInputType\n  coverDensity: Boolean\n  normalization: Int\n}\nenum TrigramSearchKind {\n  SIMILARITY\n  DISTANCE\n}\ninput TrigramFilterInputType {\n  kind: TrigramSearchKind\n  lookups: FloatLookupsInputType!\n  value: String!\n}\n```\nFor more examples, see [tests](https://github.com/devind-team/graphene-django-filter/blob/06ed0af8def8a4378b4c65a5d137ef17b6176cab/tests/test_queries_execution.py#L134).\n\n## Settings\nThe library can be customised using settings.\nTo add settings, create a dictionary\nwith name `GRAPHENE_DJANGO_FILTER` in the project\u2019s `settings.py`.\nThe default settings are as follows.\n```python\nGRAPHENE_DJANGO_FILTER = {\n    'FILTER_KEY': 'filter',\n    'AND_KEY': 'and',\n    'OR_KEY': 'or',\n    'NOT_KEY': 'not',\n}\n```\nTo read the settings, import them from the `conf` module.\n```python\nfrom graphene_django_filter.conf import settings\n\nprint(settings.FILTER_KEY)\n```\nThe `settings` object also includes fixed settings, which depend on the user's environment.\n`IS_POSTGRESQL` determinate that current database is PostgreSQL\nand `HAS_TRIGRAM_EXTENSION` that `pg_trgm` extension is installed.\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Advanced filters for Graphene",
    "version": "0.6.5",
    "project_urls": {
        "Homepage": "https://github.com/devind-team/graphene-django-filter",
        "Repository": "https://github.com/devind-team/graphene-django-filter"
    },
    "split_keywords": [
        "django",
        "graphene",
        "filter"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6b61798745029e57c6841d07e22082e1115fab1889e896ae26d200827fd1f0a5",
                "md5": "b11cfc73690248a3f496852f395d34aa",
                "sha256": "0ad4befaa997c90b1f0969d496a4739069178b02f5aed950fea7d37458c8eedd"
            },
            "downloads": -1,
            "filename": "graphene_django_filter-0.6.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b11cfc73690248a3f496852f395d34aa",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 18864,
            "upload_time": "2023-06-10T10:28:48",
            "upload_time_iso_8601": "2023-06-10T10:28:48.468788Z",
            "url": "https://files.pythonhosted.org/packages/6b/61/798745029e57c6841d07e22082e1115fab1889e896ae26d200827fd1f0a5/graphene_django_filter-0.6.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c2444d9a9bdf2ad428f61a7a79ec9438eaad01915284b01afabf1b26fb6a9667",
                "md5": "f0ff499a9760f20a377519f1ef191bda",
                "sha256": "0435daa7deb05c7c42987c22708fd314afde9671d3320225eaac1ae64341f9d0"
            },
            "downloads": -1,
            "filename": "graphene_django_filter-0.6.5.tar.gz",
            "has_sig": false,
            "md5_digest": "f0ff499a9760f20a377519f1ef191bda",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 17184,
            "upload_time": "2023-06-10T10:28:50",
            "upload_time_iso_8601": "2023-06-10T10:28:50.180552Z",
            "url": "https://files.pythonhosted.org/packages/c2/44/4d9a9bdf2ad428f61a7a79ec9438eaad01915284b01afabf1b26fb6a9667/graphene_django_filter-0.6.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-10 10:28:50",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "devind-team",
    "github_project": "graphene-django-filter",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "graphene-django-filter"
}
        
Elapsed time: 0.07841s