Skip to content

Commit

Permalink
Merge fields used in meta attribute passed on DjangoObjectType
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Hernandez committed Feb 23, 2021
1 parent 4573d3d commit aed2f78
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 3 deletions.
4 changes: 4 additions & 0 deletions graphene_django/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,9 @@ class Article(models.Model):
def __str__(self): # __unicode__ on Python 2
return self.headline

@property
def headline_with_lang(self):
return "{} - {}".format(self.lang, self.headline)

class Meta:
ordering = ("headline",)
83 changes: 81 additions & 2 deletions graphene_django/tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

import graphene
from graphene.relay import Node
from graphene.types.utils import yank_fields_from_attrs

from ..compat import IntegerRangeField, MissingType
from ..fields import DjangoConnectionField
from ..types import DjangoObjectType
from ..fields import DjangoConnectionField, DjangoListField
from ..types import DjangoObjectType, DjangoObjectTypeOptions
from ..utils import DJANGO_FILTER_INSTALLED
from .models import Article, CNNReporter, Film, FilmDetails, Reporter

Expand Down Expand Up @@ -1586,3 +1587,81 @@ class Query(graphene.ObjectType):
"allReporters": {"edges": [{"node": {"firstName": "Jane", "lastName": "Roe"}},]}
}
assert result.data == expected


def test_should_query_django_objecttype_fields_custom_meta():
class ArticleTypeOptions(DjangoObjectTypeOptions):
"""Article Type Options with extra fields"""

fields = yank_fields_from_attrs(
{"headline_with_lang": graphene.String()}, _as=graphene.Field,
)

class ArticleBaseType(DjangoObjectType):
class Meta:
abstract = True

@classmethod
def __init_subclass_with_meta__(cls, **options):
options.setdefault("_meta", ArticleTypeOptions(cls))
super(ArticleBaseType, cls).__init_subclass_with_meta__(**options)

class ArticleCustomType(ArticleBaseType):
class Meta:
model = Article
fields = (
"headline",
"lang",
"headline_with_lang",
)

class Query(graphene.ObjectType):
all_articles = DjangoListField(ArticleCustomType)

r = Reporter.objects.create(
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
)
Article.objects.create(
headline="Article Node 1",
pub_date=datetime.date.today(),
pub_date_time=datetime.datetime.now(),
reporter=r,
editor=r,
lang="es",
)
Article.objects.create(
headline="Article Node 2",
pub_date=datetime.date.today(),
pub_date_time=datetime.datetime.now(),
reporter=r,
editor=r,
lang="en",
)

schema = graphene.Schema(query=Query)
query = """
query GetAllArticles {
allArticles {
headline
lang
headlineWithLang
}
}
"""
result = schema.execute(query)
assert not result.errors
expected = {
"allArticles": [
{
"headline": "Article Node 1",
"lang": "ES",
"headlineWithLang": "es - Article Node 1",
},
{
"headline": "Article Node 2",
"lang": "EN",
"headlineWithLang": "en - Article Node 2",
},
]
}
assert result.data == expected
102 changes: 102 additions & 0 deletions graphene_django/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,33 @@ class Meta:
assert isinstance(Article._meta, ArticleTypeOptions)


def test_django_objecttype_with_custom_meta_fields():
class ArticleTypeOptions(DjangoObjectTypeOptions):
"""Article Type Options with extra fields"""

fields = {"headline_with_lang": String()}

class ArticleType(DjangoObjectType):
class Meta:
abstract = True

@classmethod
def __init_subclass_with_meta__(cls, **options):
options.setdefault("_meta", ArticleTypeOptions(cls))
super(ArticleType, cls).__init_subclass_with_meta__(**options)

class Article(ArticleType):
class Meta:
model = ArticleModel
fields = "__all__"

headline_with_lang_field = Article._meta.fields.get("headline_with_lang")

assert isinstance(Article._meta, ArticleTypeOptions)
assert headline_with_lang_field is not None
assert isinstance(headline_with_lang_field, String)


def test_schema_representation():
expected = dedent(
"""\
Expand Down Expand Up @@ -278,6 +305,81 @@ class Meta:
assert fields == ["id", "email", "films"]


@with_local_registry
def test_django_objecttype_fields_custom_meta_fields():
class ArticleTypeOptions(DjangoObjectTypeOptions):
"""Article Type Options with extra fields"""

fields = {"headline_with_lang": String()}

class ArticleType(DjangoObjectType):
class Meta:
abstract = True

@classmethod
def __init_subclass_with_meta__(cls, **options):
options.setdefault("_meta", ArticleTypeOptions(cls))
super(ArticleType, cls).__init_subclass_with_meta__(**options)

class Article(ArticleType):
class Meta:
model = ArticleModel
fields = ("editor", "lang", "importance")

fields = list(Article._meta.fields.keys())
assert fields == ["editor", "lang", "importance"]


@with_local_registry
def test_django_objecttype_fields_custom_meta_fields_include():
class ArticleTypeOptions(DjangoObjectTypeOptions):
"""Article Type Options with extra fields"""

fields = {"headline_with_lang": String()}

class ArticleType(DjangoObjectType):
class Meta:
abstract = True

@classmethod
def __init_subclass_with_meta__(cls, **options):
options.setdefault("_meta", ArticleTypeOptions(cls))
super(ArticleType, cls).__init_subclass_with_meta__(**options)

class Article(ArticleType):
class Meta:
model = ArticleModel
fields = ("headline_with_lang", "editor", "lang", "importance")

fields = list(Article._meta.fields.keys())
assert fields == ["headline_with_lang", "editor", "lang", "importance"]


@with_local_registry
def test_django_objecttype_fields_custom_meta_fields_all():
class ArticleTypeOptions(DjangoObjectTypeOptions):
"""Article Type Options with extra fields"""

fields = {"headline_with_lang": String()}

class ArticleType(DjangoObjectType):
class Meta:
abstract = True

@classmethod
def __init_subclass_with_meta__(cls, **options):
options.setdefault("_meta", ArticleTypeOptions(cls))
super(ArticleType, cls).__init_subclass_with_meta__(**options)

class Article(ArticleType):
class Meta:
model = ArticleModel
fields = "__all__"

fields = list(Article._meta.fields.keys())
assert len(fields) == len(ArticleModel._meta.get_fields()) + 1


@with_local_registry
def test_django_objecttype_fields():
class Reporter(DjangoObjectType):
Expand Down
15 changes: 14 additions & 1 deletion graphene_django/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,26 @@ def __init_subclass_with_meta__(

if not _meta:
_meta = DjangoObjectTypeOptions(cls)
elif _meta.fields:
# Exclude previous meta fields that are not in fields or are in exclude
only_fields = fields is not None and fields != ALL_FIELDS
exclude_fields = exclude is not None
if only_fields or exclude_fields:
for name in list(_meta.fields.keys()):
if (only_fields and name not in fields) or (
exclude_fields and name in exclude
):
_meta.fields.pop(name)

_meta.model = model
_meta.registry = registry
_meta.filter_fields = filter_fields
_meta.filterset_class = filterset_class
_meta.fields = django_fields
_meta.connection = connection
if _meta.fields:
_meta.fields.update(django_fields)
else:
_meta.fields = django_fields

super(DjangoObjectType, cls).__init_subclass_with_meta__(
_meta=_meta, interfaces=interfaces, **options
Expand Down

0 comments on commit aed2f78

Please sign in to comment.