10
10
from strawberry .relay import GlobalID
11
11
from strawberry .types import ExecutionResult , get_object_definition
12
12
from strawberry .types .base import WithStrawberryObjectDefinition , get_object_definition
13
+ from typing_extensions import Self
13
14
14
15
import strawberry_django
15
16
from strawberry_django .exceptions import (
25
26
)
26
27
from strawberry_django .filters import process_filters , resolve_value
27
28
from tests import models , utils
28
- from tests .types import Fruit , FruitType
29
+ from tests .types import Fruit , FruitType , Vegetable
29
30
30
31
31
32
@strawberry .enum
@@ -35,6 +36,15 @@ class Version(Enum):
35
36
THREE = "third"
36
37
37
38
39
+ @strawberry_django .filter_type (models .Vegetable , lookups = True )
40
+ class VegetableFilter :
41
+ id : auto
42
+ name : auto
43
+ AND : Optional [list [Self ]] = strawberry .UNSET
44
+ OR : Optional [list [Self ]] = strawberry .UNSET
45
+ NOT : Optional [list [Self ]] = strawberry .UNSET
46
+
47
+
38
48
@strawberry_django .filter_type (models .Color , lookups = True )
39
49
class ColorFilter :
40
50
id : auto
@@ -106,6 +116,7 @@ def filter(self, info, queryset: QuerySet, prefix):
106
116
class Query :
107
117
types : list [FruitType ] = strawberry_django .field (filters = FruitTypeFilter )
108
118
fruits : list [Fruit ] = strawberry_django .field (filters = FruitFilter )
119
+ vegetables : list [Vegetable ] = strawberry_django .field (filters = VegetableFilter )
109
120
110
121
111
122
@pytest .fixture
@@ -423,6 +434,87 @@ def test_filter_distinct(query, db, fruits):
423
434
assert len (result .data ["fruits" ]) == 1
424
435
425
436
437
+ def test_filter_and_or_not (query , db ):
438
+ v1 = models .Vegetable .objects .create (
439
+ name = "v1" , description = "d1" , world_production = 100
440
+ )
441
+ v2 = models .Vegetable .objects .create (
442
+ name = "v2" , description = "d2" , world_production = 200
443
+ )
444
+ v3 = models .Vegetable .objects .create (
445
+ name = "v3" , description = "d3" , world_production = 300
446
+ )
447
+
448
+ # Test impossible AND
449
+ result = query ("""
450
+ {
451
+ vegetables(filters: { AND: [{ name: { exact: "v1" } }, { name: { exact: "v2" } }] }) { id }
452
+ }
453
+ """ )
454
+ assert not result .errors
455
+ assert len (result .data ["vegetables" ]) == 0
456
+
457
+ # Test AND with contains
458
+ result = query ("""
459
+ {
460
+ vegetables(filters: { AND: [{ name: { contains: "v" } }, { name: { contains: "2" } }] }) { id }
461
+ }
462
+ """ )
463
+ assert not result .errors
464
+ assert len (result .data ["vegetables" ]) == 1
465
+ assert result .data ["vegetables" ][0 ]["id" ] == str (v2 .pk )
466
+
467
+ # Test OR
468
+ result = query ("""
469
+ {
470
+ vegetables(filters: { OR: [{ name: { exact: "v1" } }, { name: { exact: "v3" } }] }) { id }
471
+ }
472
+ """ )
473
+ assert not result .errors
474
+ assert len (result .data ["vegetables" ]) == 2
475
+ assert {
476
+ result .data ["vegetables" ][0 ]["id" ],
477
+ result .data ["vegetables" ][1 ]["id" ],
478
+ } == {str (v1 .pk ), str (v3 .pk )}
479
+
480
+ # Test NOT
481
+ result = query ("""
482
+ {
483
+ vegetables(filters: { NOT: [{ name: { exact: "v1" } }, { name: { exact: "v2" } }] }) { id }
484
+ }
485
+ """ )
486
+ assert not result .errors
487
+ assert len (result .data ["vegetables" ]) == 1
488
+ assert result .data ["vegetables" ][0 ]["id" ] == str (v3 .pk )
489
+
490
+ # Test interaction with simple filters. No matches due to AND logic relative to simple filters.
491
+ result = query (
492
+ """
493
+ {
494
+ vegetables(filters: { id: { exact: """
495
+ + str (v1 .pk )
496
+ + """ }, AND: [{ name: { exact: "v2" } }] }) { id }
497
+ }
498
+ """
499
+ )
500
+ assert not result .errors
501
+ assert len (result .data ["vegetables" ]) == 0
502
+
503
+ # Test interaction with simple filters. Match on same record
504
+ result = query (
505
+ """
506
+ {
507
+ vegetables(filters: { id: { exact: """
508
+ + str (v1 .pk )
509
+ + """ }, AND: [{ name: { exact: "v1" } }] }) { id }
510
+ }
511
+ """
512
+ )
513
+ assert not result .errors
514
+ assert len (result .data ["vegetables" ]) == 1
515
+ assert result .data ["vegetables" ][0 ]["id" ] == str (v1 .pk )
516
+
517
+
426
518
def test_filter_none (query , db ):
427
519
yellow = models .Color .objects .create (name = "yellow" )
428
520
models .Fruit .objects .create (name = "banana" , color = yellow )
0 commit comments