1import datetime 2from django.db.models import Count 3 4import pytest 5 6from graphene import List, NonNull, ObjectType, Schema, String 7 8from ..fields import DjangoListField 9from ..types import DjangoObjectType 10from .models import Article as ArticleModel 11from .models import Reporter as ReporterModel 12 13 14class TestDjangoListField: 15 def test_only_django_object_types(self): 16 class TestType(ObjectType): 17 foo = String() 18 19 with pytest.raises(AssertionError): 20 list_field = DjangoListField(TestType) 21 22 def test_only_import_paths(self): 23 list_field = DjangoListField("graphene_django.tests.schema.Human") 24 from .schema import Human 25 26 assert list_field._type.of_type.of_type is Human 27 28 def test_non_null_type(self): 29 class Reporter(DjangoObjectType): 30 class Meta: 31 model = ReporterModel 32 fields = ("first_name",) 33 34 list_field = DjangoListField(NonNull(Reporter)) 35 36 assert isinstance(list_field.type, List) 37 assert isinstance(list_field.type.of_type, NonNull) 38 assert list_field.type.of_type.of_type is Reporter 39 40 def test_get_django_model(self): 41 class Reporter(DjangoObjectType): 42 class Meta: 43 model = ReporterModel 44 fields = ("first_name",) 45 46 list_field = DjangoListField(Reporter) 47 assert list_field.model is ReporterModel 48 49 def test_list_field_default_queryset(self): 50 class Reporter(DjangoObjectType): 51 class Meta: 52 model = ReporterModel 53 fields = ("first_name",) 54 55 class Query(ObjectType): 56 reporters = DjangoListField(Reporter) 57 58 schema = Schema(query=Query) 59 60 query = """ 61 query { 62 reporters { 63 firstName 64 } 65 } 66 """ 67 68 ReporterModel.objects.create(first_name="Tara", last_name="West") 69 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 70 71 result = schema.execute(query) 72 73 assert not result.errors 74 assert result.data == { 75 "reporters": [{"firstName": "Tara"}, {"firstName": "Debra"}] 76 } 77 78 def test_list_field_queryset_is_not_cached(self): 79 class Reporter(DjangoObjectType): 80 class Meta: 81 model = ReporterModel 82 fields = ("first_name",) 83 84 class Query(ObjectType): 85 reporters = DjangoListField(Reporter) 86 87 schema = Schema(query=Query) 88 89 query = """ 90 query { 91 reporters { 92 firstName 93 } 94 } 95 """ 96 97 result = schema.execute(query) 98 assert not result.errors 99 assert result.data == {"reporters": []} 100 101 ReporterModel.objects.create(first_name="Tara", last_name="West") 102 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 103 104 result = schema.execute(query) 105 106 assert not result.errors 107 assert result.data == { 108 "reporters": [{"firstName": "Tara"}, {"firstName": "Debra"}] 109 } 110 111 def test_override_resolver(self): 112 class Reporter(DjangoObjectType): 113 class Meta: 114 model = ReporterModel 115 fields = ("first_name",) 116 117 class Query(ObjectType): 118 reporters = DjangoListField(Reporter) 119 120 def resolve_reporters(_, info): 121 return ReporterModel.objects.filter(first_name="Tara") 122 123 schema = Schema(query=Query) 124 125 query = """ 126 query { 127 reporters { 128 firstName 129 } 130 } 131 """ 132 133 ReporterModel.objects.create(first_name="Tara", last_name="West") 134 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 135 136 result = schema.execute(query) 137 138 assert not result.errors 139 assert result.data == {"reporters": [{"firstName": "Tara"}]} 140 141 def test_nested_list_field(self): 142 class Article(DjangoObjectType): 143 class Meta: 144 model = ArticleModel 145 fields = ("headline",) 146 147 class Reporter(DjangoObjectType): 148 class Meta: 149 model = ReporterModel 150 fields = ("first_name", "articles") 151 152 class Query(ObjectType): 153 reporters = DjangoListField(Reporter) 154 155 schema = Schema(query=Query) 156 157 query = """ 158 query { 159 reporters { 160 firstName 161 articles { 162 headline 163 } 164 } 165 } 166 """ 167 168 r1 = ReporterModel.objects.create(first_name="Tara", last_name="West") 169 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 170 171 ArticleModel.objects.create( 172 headline="Amazing news", 173 reporter=r1, 174 pub_date=datetime.date.today(), 175 pub_date_time=datetime.datetime.now(), 176 editor=r1, 177 ) 178 ArticleModel.objects.create( 179 headline="Not so good news", 180 reporter=r1, 181 pub_date=datetime.date.today(), 182 pub_date_time=datetime.datetime.now(), 183 editor=r1, 184 ) 185 186 result = schema.execute(query) 187 188 assert not result.errors 189 assert result.data == { 190 "reporters": [ 191 { 192 "firstName": "Tara", 193 "articles": [ 194 {"headline": "Amazing news"}, 195 {"headline": "Not so good news"}, 196 ], 197 }, 198 {"firstName": "Debra", "articles": []}, 199 ] 200 } 201 202 def test_override_resolver_nested_list_field(self): 203 class Article(DjangoObjectType): 204 class Meta: 205 model = ArticleModel 206 fields = ("headline",) 207 208 class Reporter(DjangoObjectType): 209 class Meta: 210 model = ReporterModel 211 fields = ("first_name", "articles") 212 213 def resolve_articles(reporter, info): 214 return reporter.articles.filter(headline__contains="Amazing") 215 216 class Query(ObjectType): 217 reporters = DjangoListField(Reporter) 218 219 schema = Schema(query=Query) 220 221 query = """ 222 query { 223 reporters { 224 firstName 225 articles { 226 headline 227 } 228 } 229 } 230 """ 231 232 r1 = ReporterModel.objects.create(first_name="Tara", last_name="West") 233 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 234 235 ArticleModel.objects.create( 236 headline="Amazing news", 237 reporter=r1, 238 pub_date=datetime.date.today(), 239 pub_date_time=datetime.datetime.now(), 240 editor=r1, 241 ) 242 ArticleModel.objects.create( 243 headline="Not so good news", 244 reporter=r1, 245 pub_date=datetime.date.today(), 246 pub_date_time=datetime.datetime.now(), 247 editor=r1, 248 ) 249 250 result = schema.execute(query) 251 252 assert not result.errors 253 assert result.data == { 254 "reporters": [ 255 {"firstName": "Tara", "articles": [{"headline": "Amazing news"}]}, 256 {"firstName": "Debra", "articles": []}, 257 ] 258 } 259 260 def test_get_queryset_filter(self): 261 class Reporter(DjangoObjectType): 262 class Meta: 263 model = ReporterModel 264 fields = ("first_name", "articles") 265 266 @classmethod 267 def get_queryset(cls, queryset, info): 268 # Only get reporters with at least 1 article 269 return queryset.annotate(article_count=Count("articles")).filter( 270 article_count__gt=0 271 ) 272 273 class Query(ObjectType): 274 reporters = DjangoListField(Reporter) 275 276 def resolve_reporters(_, info): 277 return ReporterModel.objects.all() 278 279 schema = Schema(query=Query) 280 281 query = """ 282 query { 283 reporters { 284 firstName 285 } 286 } 287 """ 288 289 r1 = ReporterModel.objects.create(first_name="Tara", last_name="West") 290 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 291 292 ArticleModel.objects.create( 293 headline="Amazing news", 294 reporter=r1, 295 pub_date=datetime.date.today(), 296 pub_date_time=datetime.datetime.now(), 297 editor=r1, 298 ) 299 300 result = schema.execute(query) 301 302 assert not result.errors 303 assert result.data == {"reporters": [{"firstName": "Tara"}]} 304 305 def test_resolve_list(self): 306 """Resolving a plain list should work (and not call get_queryset)""" 307 308 class Reporter(DjangoObjectType): 309 class Meta: 310 model = ReporterModel 311 fields = ("first_name", "articles") 312 313 @classmethod 314 def get_queryset(cls, queryset, info): 315 # Only get reporters with at least 1 article 316 return queryset.annotate(article_count=Count("articles")).filter( 317 article_count__gt=0 318 ) 319 320 class Query(ObjectType): 321 reporters = DjangoListField(Reporter) 322 323 def resolve_reporters(_, info): 324 return [ReporterModel.objects.get(first_name="Debra")] 325 326 schema = Schema(query=Query) 327 328 query = """ 329 query { 330 reporters { 331 firstName 332 } 333 } 334 """ 335 336 r1 = ReporterModel.objects.create(first_name="Tara", last_name="West") 337 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 338 339 ArticleModel.objects.create( 340 headline="Amazing news", 341 reporter=r1, 342 pub_date=datetime.date.today(), 343 pub_date_time=datetime.datetime.now(), 344 editor=r1, 345 ) 346 347 result = schema.execute(query) 348 349 assert not result.errors 350 assert result.data == {"reporters": [{"firstName": "Debra"}]} 351 352 def test_get_queryset_foreign_key(self): 353 class Article(DjangoObjectType): 354 class Meta: 355 model = ArticleModel 356 fields = ("headline",) 357 358 @classmethod 359 def get_queryset(cls, queryset, info): 360 # Rose tinted glasses 361 return queryset.exclude(headline__contains="Not so good") 362 363 class Reporter(DjangoObjectType): 364 class Meta: 365 model = ReporterModel 366 fields = ("first_name", "articles") 367 368 class Query(ObjectType): 369 reporters = DjangoListField(Reporter) 370 371 schema = Schema(query=Query) 372 373 query = """ 374 query { 375 reporters { 376 firstName 377 articles { 378 headline 379 } 380 } 381 } 382 """ 383 384 r1 = ReporterModel.objects.create(first_name="Tara", last_name="West") 385 ReporterModel.objects.create(first_name="Debra", last_name="Payne") 386 387 ArticleModel.objects.create( 388 headline="Amazing news", 389 reporter=r1, 390 pub_date=datetime.date.today(), 391 pub_date_time=datetime.datetime.now(), 392 editor=r1, 393 ) 394 ArticleModel.objects.create( 395 headline="Not so good news", 396 reporter=r1, 397 pub_date=datetime.date.today(), 398 pub_date_time=datetime.datetime.now(), 399 editor=r1, 400 ) 401 402 result = schema.execute(query) 403 404 assert not result.errors 405 assert result.data == { 406 "reporters": [ 407 {"firstName": "Tara", "articles": [{"headline": "Amazing news"}]}, 408 {"firstName": "Debra", "articles": []}, 409 ] 410 } 411