mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 12:44:15 +03:00
Improved fields ordering. Thanks @leebyron for pointing this!
Not everything yet fixed. Have to fix too in graphql-core/relay
This commit is contained in:
parent
fbd9465e57
commit
0bc0218032
|
@ -25,10 +25,10 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
|
|||
if not cls._meta.model:
|
||||
return
|
||||
only_fields = cls._meta.only_fields
|
||||
reverse_fields = tuple(get_reverse_fields(cls._meta.model))
|
||||
all_fields = (list(cls._meta.model._meta.fields) +
|
||||
list(reverse_fields) +
|
||||
list(cls._meta.model._meta.local_many_to_many))
|
||||
reverse_fields = get_reverse_fields(cls._meta.model)
|
||||
all_fields = sorted(list(cls._meta.model._meta.fields) +
|
||||
list(reverse_fields) +
|
||||
list(cls._meta.model._meta.local_many_to_many))
|
||||
|
||||
for field in all_fields:
|
||||
is_not_in_only = only_fields and field.name not in only_fields
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import inspect
|
||||
import six
|
||||
from functools import total_ordering
|
||||
from graphql.core.type import (
|
||||
GraphQLField,
|
||||
GraphQLList,
|
||||
|
@ -16,8 +17,10 @@ from graphene.core.types import BaseObjectType
|
|||
from graphene.core.scalars import GraphQLSkipField
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Field(object):
|
||||
SKIP = GraphQLSkipField
|
||||
creation_counter = 0
|
||||
|
||||
def __init__(self, field_type, name=None, resolve=None, required=False, args=None, description='', **extra_args):
|
||||
self.field_type = field_type
|
||||
|
@ -29,6 +32,8 @@ class Field(object):
|
|||
self.name = name
|
||||
self.description = description or self.__doc__
|
||||
self.object_type = None
|
||||
self.creation_counter = Field.creation_counter
|
||||
Field.creation_counter += 1
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
if not self.name:
|
||||
|
@ -122,6 +127,21 @@ class Field(object):
|
|||
return '<%s: %s>' % (path, name)
|
||||
return '<%s>' % path
|
||||
|
||||
def __eq__(self, other):
|
||||
# Needed for @total_ordering
|
||||
if isinstance(other, Field):
|
||||
return self.creation_counter == other.creation_counter
|
||||
return NotImplemented
|
||||
|
||||
def __lt__(self, other):
|
||||
# This is needed because bisect does not take a comparison function.
|
||||
if isinstance(other, Field):
|
||||
return self.creation_counter < other.creation_counter
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.creation_counter)
|
||||
|
||||
|
||||
class NativeField(Field):
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from graphene.utils import cached_property
|
||||
from collections import OrderedDict
|
||||
|
||||
DEFAULT_NAMES = ('description', 'name', 'interface',
|
||||
'type_name', 'interfaces', 'proxy')
|
||||
|
@ -66,12 +67,8 @@ class Options(object):
|
|||
fields = []
|
||||
for parent in self.parents:
|
||||
fields.extend(parent._meta.fields)
|
||||
return self.local_fields + fields
|
||||
return sorted(self.local_fields + fields)
|
||||
|
||||
@cached_property
|
||||
def fields_map(self):
|
||||
return {f.field_name: f for f in self.fields}
|
||||
|
||||
@cached_property
|
||||
def internal_fields_map(self):
|
||||
return {f.name: f for f in self.fields}
|
||||
return OrderedDict([(f.field_name, f) for f in self.fields])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import inspect
|
||||
import six
|
||||
from collections import OrderedDict
|
||||
|
||||
from graphql.core.type import (
|
||||
GraphQLObjectType,
|
||||
|
@ -49,10 +50,9 @@ class ObjectTypeMeta(type):
|
|||
new_class.add_extra_fields()
|
||||
|
||||
new_fields = new_class._meta.local_fields
|
||||
field_names = {f.name:f for f in new_fields}
|
||||
field_names = {f.name: f for f in new_fields}
|
||||
|
||||
for base in parents:
|
||||
original_base = base
|
||||
if not hasattr(base, '_meta'):
|
||||
# Things without _meta aren't functional models, so they're
|
||||
# uninteresting parents.
|
||||
|
@ -132,11 +132,9 @@ class BaseObjectType(object):
|
|||
@memoize
|
||||
@register_internal_type
|
||||
def internal_type(cls, schema):
|
||||
fields_map = cls._meta.internal_fields_map
|
||||
fields = lambda: {
|
||||
name: field.internal_field(schema)
|
||||
for name, field in fields_map.items()
|
||||
}
|
||||
fields_list = cls._meta.fields
|
||||
fields = lambda: OrderedDict([(f.name, f.internal_field(schema))
|
||||
for f in fields_list])
|
||||
if cls._meta.interface:
|
||||
return GraphQLInterfaceType(
|
||||
cls._meta.type_name,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import collections
|
||||
from collections import Iterable, OrderedDict
|
||||
|
||||
from graphql_relay.connection.arrayconnection import (
|
||||
connectionFromArray
|
||||
|
@ -30,7 +30,7 @@ class ConnectionField(Field):
|
|||
if resolved:
|
||||
resolved = self.wrap_resolved(resolved, instance, args, info)
|
||||
assert isinstance(
|
||||
resolved, collections.Iterable), 'Resolved value from the connection field have to be iterable'
|
||||
resolved, Iterable), 'Resolved value from the connection field have to be iterable'
|
||||
return connectionFromArray(resolved, args)
|
||||
|
||||
@memoize
|
||||
|
@ -71,7 +71,7 @@ class NodeTypeField(LazyField):
|
|||
if resolved_global_id.type == self.field_object_type._meta.type_name:
|
||||
return node_field.resolver(instance, args, info)
|
||||
|
||||
args = {a.name: a for a in node_field.args}
|
||||
args = OrderedDict([(a.name, a) for a in node_field.args])
|
||||
field = Field(self.field_object_type, id=args['id'], resolve=resolver)
|
||||
field.contribute_to_class(self.object_type, self.field_name)
|
||||
|
||||
|
|
|
@ -63,13 +63,13 @@ def test_interface_resolve_type():
|
|||
|
||||
def test_object_type():
|
||||
object_type = Human.internal_type(schema)
|
||||
internal_fields_map = Human._meta.internal_fields_map
|
||||
fields_map = Human._meta.fields_map
|
||||
assert Human._meta.interface is False
|
||||
assert isinstance(object_type, GraphQLObjectType)
|
||||
assert object_type.get_fields() == {
|
||||
'headline': internal_fields_map['headline'].internal_field(schema),
|
||||
'id': internal_fields_map['id'].internal_field(schema),
|
||||
'reporter': internal_fields_map['reporter'].internal_field(schema),
|
||||
'pubDate': internal_fields_map['pubDate'].internal_field(schema),
|
||||
'headline': fields_map['headline'].internal_field(schema),
|
||||
'id': fields_map['id'].internal_field(schema),
|
||||
'reporter': fields_map['reporter'].internal_field(schema),
|
||||
'pubDate': fields_map['pub_date'].internal_field(schema),
|
||||
}
|
||||
assert object_type.get_interfaces() == [DjangoNode.internal_type(schema)]
|
||||
|
|
Loading…
Reference in New Issue
Block a user