mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-07-06 21:33:29 +03:00
Merge fields used in meta attribute passed on DjangoObjectType
This commit is contained in:
parent
4573d3db53
commit
aed2f78bdb
|
@ -115,5 +115,9 @@ class Article(models.Model):
|
||||||
def __str__(self): # __unicode__ on Python 2
|
def __str__(self): # __unicode__ on Python 2
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
|
@property
|
||||||
|
def headline_with_lang(self):
|
||||||
|
return "{} - {}".format(self.lang, self.headline)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ("headline",)
|
ordering = ("headline",)
|
||||||
|
|
|
@ -10,10 +10,11 @@ from py.test import raises
|
||||||
|
|
||||||
import graphene
|
import graphene
|
||||||
from graphene.relay import Node
|
from graphene.relay import Node
|
||||||
|
from graphene.types.utils import yank_fields_from_attrs
|
||||||
|
|
||||||
from ..compat import IntegerRangeField, MissingType
|
from ..compat import IntegerRangeField, MissingType
|
||||||
from ..fields import DjangoConnectionField
|
from ..fields import DjangoConnectionField, DjangoListField
|
||||||
from ..types import DjangoObjectType
|
from ..types import DjangoObjectType, DjangoObjectTypeOptions
|
||||||
from ..utils import DJANGO_FILTER_INSTALLED
|
from ..utils import DJANGO_FILTER_INSTALLED
|
||||||
from .models import Article, CNNReporter, Film, FilmDetails, Reporter
|
from .models import Article, CNNReporter, Film, FilmDetails, Reporter
|
||||||
|
|
||||||
|
@ -1586,3 +1587,81 @@ def test_connection_should_allow_offset_filtering_with_after():
|
||||||
"allReporters": {"edges": [{"node": {"firstName": "Jane", "lastName": "Roe"}},]}
|
"allReporters": {"edges": [{"node": {"firstName": "Jane", "lastName": "Roe"}},]}
|
||||||
}
|
}
|
||||||
assert result.data == expected
|
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
|
||||||
|
|
|
@ -114,6 +114,33 @@ def test_django_objecttype_with_custom_meta():
|
||||||
assert isinstance(Article._meta, ArticleTypeOptions)
|
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():
|
def test_schema_representation():
|
||||||
expected = dedent(
|
expected = dedent(
|
||||||
"""\
|
"""\
|
||||||
|
@ -278,6 +305,81 @@ def test_django_objecttype_only_fields():
|
||||||
assert fields == ["id", "email", "films"]
|
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
|
@with_local_registry
|
||||||
def test_django_objecttype_fields():
|
def test_django_objecttype_fields():
|
||||||
class Reporter(DjangoObjectType):
|
class Reporter(DjangoObjectType):
|
||||||
|
|
|
@ -256,13 +256,26 @@ class DjangoObjectType(ObjectType):
|
||||||
|
|
||||||
if not _meta:
|
if not _meta:
|
||||||
_meta = DjangoObjectTypeOptions(cls)
|
_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.model = model
|
||||||
_meta.registry = registry
|
_meta.registry = registry
|
||||||
_meta.filter_fields = filter_fields
|
_meta.filter_fields = filter_fields
|
||||||
_meta.filterset_class = filterset_class
|
_meta.filterset_class = filterset_class
|
||||||
_meta.fields = django_fields
|
|
||||||
_meta.connection = connection
|
_meta.connection = connection
|
||||||
|
if _meta.fields:
|
||||||
|
_meta.fields.update(django_fields)
|
||||||
|
else:
|
||||||
|
_meta.fields = django_fields
|
||||||
|
|
||||||
super(DjangoObjectType, cls).__init_subclass_with_meta__(
|
super(DjangoObjectType, cls).__init_subclass_with_meta__(
|
||||||
_meta=_meta, interfaces=interfaces, **options
|
_meta=_meta, interfaces=interfaces, **options
|
||||||
|
|
Loading…
Reference in New Issue
Block a user