Skip to content

Commit 5f7570b

Browse files
authored
Add lquery field type
feat: Add lquery field type
2 parents 7048a4c + 6658fd3 commit 5f7570b

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

django_ltree/fields.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,8 @@ def get_db_prep_value(self, value, connection, prepared=False):
102102
return str(PathValue(value))
103103

104104
raise ValueError("Unknown value type {}".format(type(value)))
105+
106+
107+
class LqueryField(PathField):
108+
def db_type(self, connection):
109+
return "lquery"

tests/test_lquery_field.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from django.contrib.postgres.fields import ArrayField
2+
from django.db.models import Value
3+
from taxonomy.models import Taxonomy
4+
5+
from django_ltree.fields import LqueryField, PathField
6+
7+
8+
def test_lquery_field_db_type():
9+
"""Test that LqueryField returns correct database type."""
10+
field = LqueryField()
11+
assert field.db_type(connection=None) == "lquery"
12+
13+
14+
def test_lquery_field_inherits_from_pathfield():
15+
"""Test that LqueryField inherits PathField functionality."""
16+
field = LqueryField()
17+
assert isinstance(field, PathField)
18+
19+
# Should inherit PathField's value processing
20+
assert field.get_prep_value("simple.path") == "simple.path"
21+
assert field.get_prep_value(["multi", "part", "path"]) == "multi.part.path"
22+
23+
24+
def test_lquery_field_basic_validation():
25+
"""Test that LqueryField accepts valid lquery patterns."""
26+
from django.db import models
27+
28+
class TestModel(models.Model):
29+
pattern = LqueryField()
30+
31+
class Meta:
32+
app_label = 'tests'
33+
34+
# Valid lquery patterns should not raise ValidationError
35+
valid_patterns = [
36+
"simple.path",
37+
"*.wildcard.path",
38+
"path.*.with.wildcard",
39+
"f63969a8-536f-4c80-a0a3-fafdb53cb7cf.*"
40+
]
41+
42+
for pattern in valid_patterns:
43+
instance = TestModel(pattern=pattern)
44+
instance.full_clean() # Should not raise
45+
46+
47+
def test_lquery_pattern_matching(db):
48+
"""Test basic lquery pattern matching with existing Taxonomy model."""
49+
# Create some test data using the existing Taxonomy model
50+
Taxonomy.objects.create(path="tenant_a.departments.hr", name="HR Department")
51+
Taxonomy.objects.create(path="tenant_a.departments.finance", name="Finance Department")
52+
Taxonomy.objects.create(path="tenant_b.projects.alpha", name="Project Alpha")
53+
Taxonomy.objects.create(path="shared.public.docs", name="Public Documentation")
54+
55+
# Test basic pattern matching
56+
hr_matches = Taxonomy.objects.filter(path__match="tenant_a.departments.*")
57+
assert hr_matches.count() == 2
58+
59+
# Test wildcard pattern
60+
tenant_a_matches = Taxonomy.objects.filter(path__match="tenant_a.*")
61+
assert tenant_a_matches.count() == 2
62+
63+
64+
def test_lquery_array_contains_lookup(db):
65+
"""Test the key feature: contains lookup with array of lquery patterns."""
66+
# Create test data
67+
Taxonomy.objects.create(path="tenant_a.departments.hr", name="HR")
68+
Taxonomy.objects.create(path="tenant_a.projects.alpha", name="Alpha Project")
69+
Taxonomy.objects.create(path="tenant_b.departments.eng", name="Engineering")
70+
Taxonomy.objects.create(path="shared.public.docs", name="Docs")
71+
72+
# Test array of patterns with contains lookup
73+
patterns = [
74+
"tenant_a.departments.*", # HR department
75+
"shared.public.*", # Public docs
76+
]
77+
78+
output_field = ArrayField(base_field=LqueryField())
79+
80+
matching = Taxonomy.objects.filter(
81+
path__contains=Value(patterns, output_field=output_field)
82+
)
83+
84+
# Should match HR and public docs (2 items)
85+
assert matching.count() == 2
86+
87+
matched_names = set(item.name for item in matching)
88+
assert "HR" in matched_names
89+
assert "Docs" in matched_names

0 commit comments

Comments
 (0)