8000 Support base class relations and reverse for proxy models (#1380) · graphql-python/graphene-django@b1abebd · GitHub
[go: up one dir, main page]

Skip to content

Commit b1abebd

Browse files
Support base class relations and reverse for proxy models (#1380)
* support reverse relationship for proxy models * support multi table inheritence * update query test for multi table inheritance * remove debugger * support local many to many in model inheritance * format and lint --------- Co-authored-by: Firas K <3097061+firaskafri@users.noreply.github.com>
1 parent 0de35ca commit b1abebd
< 8000 /div>

File tree

6 files changed

+387
-27
lines changed

6 files changed

+387
-27
lines changed

graphene_django/tests/models.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Reporter(models.Model):
4646
a_choice = models.IntegerField(choices=CHOICES, null=True, blank=True)
4747
objects = models.Manager()
4848
doe_objects = DoeReporterManager()
49+
fans = models.ManyToManyField(Person)
4950

5051
reporter_type = models.IntegerField(
5152
"Reporter Type",
@@ -90,6 +91,16 @@ class Meta:
9091
objects = CNNReporterManager()
9192

9293

94+
class APNewsReporter(Reporter):
95+
"""
96+
This class only inherits from Reporter for testing multi table inheritence
97+
similar to what you'd see in django-polymorphic
98+
"""
99+
100+
alias = models.CharField(max_length=30)
101+
objects = models.Manager()
102+
103+
93104
class Article(models.Model):
94105
headline = models.CharField(max_length=100)
95106
pub_date = models.DateField(auto_now_add=True)

graphene_django/tests/test_query.py

Lines changed: 305 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,16 @@
1515
from ..fields import DjangoConnectionField
1616
from ..types import DjangoObjectType
1717
from ..utils import DJANGO_FILTER_INSTALLED
18-
from .models import Article, CNNReporter, Film, FilmDetails, Person, Pet, Reporter
18+
from .models import (
19+
Article,
20+
CNNReporter,
21+
Film,
22+
FilmDetails,
23+
Person,
24+
Pet,
25+
Reporter,
26+
APNewsReporter,
27+
)
1928

2029

2130
def test_should_query_only_fields():
@@ -1064,6 +1073,301 @@ class Query(graphene.ObjectType):
10641073
assert result.data == expected
10651074

10661075

1076+
def test_model_inheritance_support_reverse_relationships():
1077+
"""
1078+
This test asserts that we can query reverse relationships for all Reporters and proxied Reporters and multi table Reporters.
1079+
"""
1080+
1081+
class FilmType(DjangoObjectType):
1082+
class Meta:
1083+
model = Film
1084+
fields = "__all__"
1085+
1086+
class ReporterType(DjangoObjectType):
1087+
class Meta:
1088+
model = Reporter
1089+
interfaces = (Node,)
1090+
use_connection = True
1091+
fields = "__all__"
1092+
1093+
class CNNReporterType(DjangoObjectType):
1094+
class Meta:
1095+
model = CNNReporter
1096+
interfaces = (Node,)
1097+
use_connection = True
1098+
fields = "__all__"
1099+
1100+
class APNewsReporterType(DjangoObjectType):
1101+
class Meta:
1102+
model = APNewsReporter
1103+
interfaces = (Node,)
1104+
use_connection = True
1105+
fields = "__all__"
1106+
1107+
film = Film.objects.create(genre="do")
1108+
1109+
reporter = Reporter.objects.create(
1110+
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
1111+
)
1112+
1113+
cnn_reporter = CNNReporter.objects.create(
1114+
first_name="Some",
1115+
last_name="Guy",
1116+
email="someguy@cnn.com",
1117+
a_choice=1,
1118+
reporter_type=2, # set this guy to be CNN
1119+
)
1120+
1121+
ap_news_reporter = APNewsReporter.objects.create(
1122+
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
1123+
)
1124+
1125+
film.reporters.add(cnn_reporter, ap_news_reporter)
1126+
film.save()
1127+
1128+
class Query(graphene.ObjectType):
1129+
all_reporters = DjangoConnectionField(ReporterType)
1130+
cnn_reporters = DjangoConnectionField(CNNReporterType)
1131+
ap_news_reporters = DjangoConnectionField(APNewsReporterType)
1132+
1133+
schema = graphene.Schema(query=Query)
1134+
query = """
1135+
query ProxyModelQuery {
1136+
allReporters {
1137+
edges {
1138+
node {
1139+
id
1140+
films {
1141+
id
1142+
}
1143+
}
1144+
}
1145+
}
1146+
cnnReporters {
1147+
edges {
1148+
node {
1149+
id
1150+
films {
1151+
id
1152+
}
1153+
}
1154+
}
1155+
}
1156+
apNewsReporters {
1157+
edges {
1158+
node {
1159+
id
1160+
films {
1161+
id
1162+
}
1163+
}
1164+
}
1165+
}
1166+
}
1167+
"""
1168+
1169+
expected = {
1170+
"allReporters": {
1171+
"edges": [
1172+
{
1173+
"node": {
1174+
"id": to_global_id("ReporterType", reporter.id),
1175+
"films": [],
1176+
},
1177+
},
1178+
{
1179+
"node": {
1180+
"id": to_global_id("ReporterType", cnn_reporter.id),
1181+
"films": [{"id": f"{film.id}"}],
1182+
},
1183+
},
1184+
{
1185+
"node": {
1186+
"id": to_global_id("ReporterType", ap_news_reporter.id),
1187+
"films": [{"id": f"{film.id}"}],
1188+
},
1189+
},
1190+
]
1191+
},
1192+
"cnnReporters": {
1193+
"edges": [
1194+
{
1195+
"node": {
1196+
"id": to_global_id("CNNReporterType", cnn_reporter.id),
1197+
"films": [{"id": f"{film.id}"}],
1198+
}
1199+
}
1200+
]
1201+
},
1202+
"apNewsReporters": {
1203+
"edges": [
1204+
{
1205+
"node": {
1206+
"id": to_global_id("APNewsReporterType", ap_news_reporter.id),
1207+
"films": [{"id": f"{film.id}"}],
1208+
}
1209+
}
1210+
]
1211+
},
1212+
}
1213+
1214+
result = schema.execute(query)
1215+
assert result.data == expected
1216+
1217+
1218+
def test_model_inheritance_support_local_relationships():
1219+
"""
1220+
This test asserts that we can query local relationships for all Reporters and proxied Reporters and multi table Reporters.
1221+
"""
1222+
1223+
class PersonType(DjangoObjectType):
1224+
class Meta:
1225+
model = Person
1226+
fields = "__all__"
1227+
1228+
class ReporterType(DjangoObjectType):
1229+
class Meta:
1230+
model = Reporter
1231+
interfaces = (Node,)
1232+
use_connection = True
1233+
fields = "__all__"
1234+
1235+
class CNNReporterType(DjangoObjectType):
1236+
class Meta:
1237+
model = CNNReporter
1238+
interfaces = (Node,)
1239+
use_connection = True
1240+
fields = "__all__"
1241+
1242+
class APNewsReporterType(DjangoObjectType):
1243+
class Meta:
1244+
model = APNewsReporter
1245+
interfaces = (Node,)
1246+
use_connection = True
1247+
fields = "__all__"
1248+
1249+
film = Film.objects.create(genre="do")
1250+
1251+
reporter = Reporter.objects.create(
1252+
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
1253+
)
1254+
1255+
reporter_fan = Person.objects.create(name="Reporter Fan")
1256+
1257+
reporter.fans.add(reporter_fan)
1258+
reporter.save()
1259+
1260+
cnn_reporter = CNNReporter.objects.create(
1261+
first_name="Some",
1262+
last_name="Guy",
1263+
email="someguy@cnn.com",
1264+
a_choice=1,
1265+
reporter_type=2, # set this guy to be CNN
1266+
)
1267+
cnn_fan = Person.objects.create(name="CNN Fan")
1268+
cnn_reporter.fans.add(cnn_fan)
1269+
cnn_reporter.save()
1270+
1271+
ap_news_reporter = APNewsReporter.objects.create(
1272+
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
1273+
)
1274+
ap_news_fan = Person.objects.create(name="AP News Fan")
1275+
ap_news_reporter.fans.add(ap_news_fan)
1276+
ap_news_reporter.save()
1277+
1278+
film.reporters.add(cnn_reporter, ap_news_reporter)
1279+
film.save()
1280+
1281+
class Query(graphene.ObjectType):
1282+
all_reporters = DjangoConnectionField(ReporterType)
1283+
cnn_reporters = DjangoConnectionField(CNNReporterType)
1284+
ap_news_reporters = DjangoConnectionField(APNewsReporterType)
1285+
1286+
schema = graphene.Schema(query=Query)
1287+
query = """
1288+
query ProxyModelQuery {
1289+
allReporters {
1290+
edges {
1291+
node {
1292+
id
1293+
fans {
1294+
name
1295+
}
1296+
}
1297+
}
1298+
}
1299+
cnnReporters {
1300+
edges {
1301+
node {
1302+
id
1303+
fans {
1304+
name
1305+
}
1306+
}
1307+
}
1308+
}
1309+
apNewsReporters {
1310+
edges {
1311+
node {
1312+
id
1313+
fans {
1314+
name
1315+
}
1316+
}
1317+
}
1318+
}
1319+
}
1320+
"""
1321+
1322+
expected = {
1323+
"allReporters": {
1324+
"edges": [
1325+
{
1326+
"node": {
1327+
"id": to_global_id("ReporterType", reporter.id),
1328+
"fans": [{"name": f"{reporter_fan.name}"}],
1329+
},
1330+
},
1331+
{
1332+
"node": {
1333+
"id": to_global_id("ReporterType", cnn_reporter.id),
1334+
"fans": [{"name": f"{cnn_fan.name}"}],
1335+
},
1336+
},
1337+
{
1338+
"node": {
1339+
"id": to_global_id("ReporterType", ap_news_reporter.id),
1340+
"fans": [{"name": f"{ap_news_fan.name}"}],
1341+
},
1342+
},
1343+
]
1344+
},
1345+
"cnnReporters": {
1346+
"edges": [
1347+
{
1348+
"node": {
1349+
"id": to_global_id("CNNReporterType", cnn_reporter.id),
1350+
"fans": [{"name": f"{cnn_fan.name}"}],
1351+
}
1352+
}
1353+
]
1354+
},
1355+
"apNewsReporters": {
1356+
"edges": [
1357+
{
1358+
"node": {
1359+
"id": to_global_id("APNewsReporterType", ap_news_reporter.id),
1360+
"fans": [{"name": f"{ap_news_fan.name}"}],
1361+
}
1362+
}
1363+
]
1364+
},
1365+
}
1366+
1367+
result = schema.execute(query)
1368+
assert result.data == expected
1369+
1370+
10671371
def test_should_resolve_get_queryset_connectionfields():
10681372
reporter_1 = Reporter.objects.create(
10691373
first_n 10000 ame="John", last_name="Doe", email="johndoe@example.com", a_choice=1

graphene_django/tests/test_schema.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,18 @@ class Meta:
3333
fields = "__all__"
3434

3535
fields = list(ReporterType2._meta.fields.keys())
36-
assert fields[:-2] == [
36+
assert fields[:-3] == [
3737
"id",
3838
"first_name",
3939
"last_name",
4040
"email",
4141
"pets",
4242
"a_choice",
43+
"fans",
4344
"reporter_type",
4445
]
4546

46-
assert sorted(fields[-2:]) == ["articles", "films"]
47+
assert sorted(fields[-3:]) == ["apnewsreporter", "articles", "films"]
4748

4849

4950
def test_should_map_only_few_fields():

graphene_django/tests/test_types.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,17 @@ def test_django_get_node(get):
6767
def test_django_objecttype_map_correct_fields():
6868
fields = Reporter._meta.fields
6969
fields = list(fields.keys())
70-
assert fields[:-2] == [
70+
assert fields[:-3] == [
7171
"id",
7272
"first_name",
7373
"last_name",
7474
"email",
7575
"pets",
7676
"a_choice",
77+
"fans",
7778
"reporter_type",
7879
]
79-
assert sorted(fields[-2:]) == ["articles", "films"]
80+
assert sorted(fields[-3:]) == ["apnewsreporter", "articles", "films"]
8081

8182

8283
def test_django_objecttype_with_node_have_correct_fields():

0 commit comments

Comments
 (0)
0