Skip to content

Commit 18db46e

Browse files
committed
Removed Meta inheritance in favor of __init_subclass_with_meta__
1 parent cec1a84 commit 18db46e

File tree

1 file changed

+55
-65
lines changed

1 file changed

+55
-65
lines changed

graphene_django/types.py

Lines changed: 55 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,103 +3,93 @@
33
import six
44

55
from django.utils.functional import SimpleLazyObject
6-
from graphene import Field, ObjectType
7-
from graphene.types.objecttype import ObjectTypeMeta
8-
from graphene.types.options import Options
9-
from graphene.types.utils import merge, yank_fields_from_attrs
10-
from graphene.utils.is_base_type import is_base_type
6+
from graphene import Field
7+
from graphene.relay import Connection, Node
8+
from graphene.types.objecttype import ObjectType, ObjectTypeOptions
9+
from graphene.types.utils import yank_fields_from_attrs
1110

1211
from .converter import convert_django_field_with_choices
1312
from .registry import Registry, get_global_registry
1413
from .utils import (DJANGO_FILTER_INSTALLED, get_model_fields,
1514
is_valid_django_model)
1615

1716

18-
def construct_fields(options):
19-
_model_fields = get_model_fields(options.model)
20-
only_fields = options.only_fields
21-
exclude_fields = options.exclude_fields
17+
def construct_fields(model, registry, only_fields, exclude_fields):
18+
_model_fields = get_model_fields(model)
2219

2320
fields = OrderedDict()
2421
for name, field in _model_fields:
25-
is_not_in_only = only_fields and name not in options.only_fields
26-
is_already_created = name in options.fields
27-
is_excluded = name in exclude_fields or is_already_created
22+
is_not_in_only = only_fields and name not in only_fields
23+
# is_already_created = name in options.fields
24+
is_excluded = name in exclude_fields # or is_already_created
2825
# https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_query_name
2926
is_no_backref = str(name).endswith('+')
3027
if is_not_in_only or is_excluded or is_no_backref:
3128
# We skip this field if we specify only_fields and is not
3229
# in there. Or when we exclude this field in exclude_fields.
3330
# Or when there is no back reference.
3431
continue
35-
converted = convert_django_field_with_choices(field, options.registry)
32+
converted = convert_django_field_with_choices(field, registry)
3633
fields[name] = converted
3734

3835
return fields
3936

4037

41-
class DjangoObjectTypeMeta(ObjectTypeMeta):
42-
43-
@staticmethod
44-
def __new__(cls, name, bases, attrs):
45-
# Also ensure initialization is only performed for subclasses of
46-
# DjangoObjectType
47-
if not is_base_type(bases, DjangoObjectTypeMeta):
48-
return type.__new__(cls, name, bases, attrs)
49-
50-
defaults = dict(
51-
name=name,
52-
description=attrs.pop('__doc__', None),
53-
model=None,
54-
local_fields=None,
55-
only_fields=(),
56-
exclude_fields=(),
57-
interfaces=(),
58-
skip_registry=False,
59-
registry=None
60-
)
61-
if DJANGO_FILTER_INSTALLED:
62-
# In case Django filter is available, then
63-
# we allow more attributes in Meta
64-
defaults.update(
65-
filter_fields=(),
66-
)
67-
68-
options = Options(
69-
attrs.pop('Meta', None),
70-
**defaults
71-
)
72-
if not options.registry:
73-
options.registry = get_global_registry()
74-
assert isinstance(options.registry, Registry), (
75-
'The attribute registry in {}.Meta needs to be an instance of '
76-
'Registry, received "{}".'
77-
).format(name, options.registry)
78-
assert is_valid_django_model(options.model), (
38+
class DjangoObjectTypeOptions(ObjectTypeOptions):
39+
model = None # type: Model
40+
registry = None # type: Registry
41+
connection = None # type: Type[Connection]
42+
43+
filter_fields = ()
44+
45+
46+
class DjangoObjectType(ObjectType):
47+
@classmethod
48+
def __init_subclass_with_meta__(cls, model=None, registry=None, skip_registry=False,
49+
only_fields=(), exclude_fields=(), filter_fields=None, connection=None, use_connection=None, interfaces=(), **options):
50+
assert is_valid_django_model(model), (
7951
'You need to pass a valid Django Model in {}.Meta, received "{}".'
80-
).format(name, options.model)
52+
).format(cls.__name__, model)
53+
54+
if not registry:
55+
registry = get_global_registry()
8156

82-
cls = ObjectTypeMeta.__new__(cls, name, bases, dict(attrs, _meta=options))
57+
assert isinstance(registry, Registry), (
58+
'The attribute registry in {} needs to be an instance of '
59+
'Registry, received "{}".'
60+
).format(cls.__name__, registry)
8361

84-
options.registry.register(cls)
62+
if not DJANGO_FILTER_INSTALLED and filter_fields:
63+
raise Exception("Can only set filter_fields if Django-Filter is installed")
8564

86-
options.django_fields = yank_fields_from_attrs(
87-
construct_fields(options),
65+
django_fields = yank_fields_from_attrs(
66+
construct_fields(model, registry, only_fields, exclude_fields),
8867
_as=Field,
8968
)
90-
options.fields = merge(
91-
options.interface_fields,
92-
options.django_fields,
93-
options.base_fields,
94-
options.local_fields
95-
)
9669

97-
return cls
70+
if use_connection is None and interfaces:
71+
use_connection = any((issubclass(interface, Node) for interface in interfaces))
72+
73+
if use_connection and not connection:
74+
# We create the connection automatically
75+
connection = Connection.create_type('{}Connection'.format(cls.__name__), node=cls)
76+
77+
if connection is not None:
78+
assert issubclass(connection, Connection), "The connection must be a Connection. Received {}".format(connection.__name__)
9879

80+
_meta = DjangoObjectTypeOptions(cls)
81+
_meta.model = model
82+
_meta.registry = registry
83+
_meta.filter_fields = filter_fields
84+
_meta.fields = django_fields
85+
_meta.connection = connection
9986

100-
class DjangoObjectType(six.with_metaclass(DjangoObjectTypeMeta, ObjectType)):
87+
super(DjangoObjectType, cls).__init_subclass_with_meta__(_meta=_meta, interfaces=interfaces, **options)
88+
89+
if not skip_registry:
90+
registry.register(cls)
10191

102-
def resolve_id(self, args, context, info):
92+
def resolve_id(self):
10393
return self.pk
10494

10595
@classmethod

0 commit comments

Comments
 (0)