Skip to content

Commit 2ed0b56

Browse files
committed
Implement composite member lookup
Closes #9
1 parent 8392315 commit 2ed0b56

File tree

5 files changed

+83
-2
lines changed

5 files changed

+83
-2
lines changed

postgres_composite_types/composite_type.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ def __new__(cls, name, bases, attrs):
8787
new_cls = super().__new__(cls, name, bases, attrs)
8888
new_cls._meta = meta_obj
8989

90+
for _, field in new_cls._meta.fields:
91+
new_cls.Field.register_lookup(
92+
type(
93+
f"{name}{field.attname}Lookup",
94+
(models.Transform,),
95+
{
96+
"lookup_name": field.attname,
97+
"arity": 1,
98+
"template": f'(%(expressions)s)."{field.column}"',
99+
},
100+
)
101+
)
102+
90103
meta_obj.model = new_cls
91104

92105
return new_cls

tests/migrations/0001_initial.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
DescriptorType,
1212
OptionalBits,
1313
Point,
14+
RenamedMemberType,
1415
SimpleType,
1516
)
1617

@@ -28,4 +29,5 @@ class Migration(migrations.Migration):
2829
Box.Operation(),
2930
DateRange.Operation(),
3031
DescriptorType.Operation(),
32+
RenamedMemberType.Operation(),
3133
]

tests/migrations/0002_models.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88

99
class Migration(migrations.Migration):
10-
1110
initial = True
1211

1312
dependencies = [
@@ -115,4 +114,10 @@ class Migration(migrations.Migration):
115114
("test_field", tests.models.SimpleTypeField()),
116115
],
117116
),
117+
migrations.CreateModel(
118+
name="RenamedMemberModel",
119+
fields=[
120+
("field", tests.models.RenamedMemberTypeField()),
121+
],
122+
),
118123
]

tests/models.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,19 @@ class DescriptorModel(models.Model):
123123
"""Has a composite type with a field implementing a custom descriptor"""
124124

125125
field = DescriptorType.Field()
126+
127+
128+
class RenamedMemberType(CompositeType):
129+
"""Has a field with a different name in ORM vs db"""
130+
131+
class Meta:
132+
db_type = "test_renamed_member"
133+
134+
orm_name = models.CharField(db_column="db_name", max_length=32)
135+
other = models.BooleanField(default=False)
136+
137+
138+
class RenamedMemberModel(models.Model):
139+
"""Has a composite type with a member attr name that differs from the column name"""
140+
141+
field = RenamedMemberType.Field()

tests/test_more.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
"""
22
Tests for composite fields in combination with other interesting fields.
33
"""
4+
import datetime
45

56
from django.db.migrations.writer import MigrationWriter
67
from django.test import TestCase
78

8-
from .models import Box, Card, DescriptorModel, DescriptorType, Hand, Item, Point
9+
from .models import (
10+
Box,
11+
Card,
12+
DescriptorModel,
13+
DescriptorType,
14+
Hand,
15+
Item,
16+
Point,
17+
RenamedMemberModel,
18+
RenamedMemberType,
19+
SimpleModel,
20+
SimpleType,
21+
)
922

1023

1124
class TestArrayFields(TestCase):
@@ -115,3 +128,35 @@ def test_set(self):
115128
model = DescriptorModel(field=DescriptorType(value=0))
116129
model.field.value = 14
117130
self.assertEqual(model.field.value, 42)
131+
132+
133+
class TestMemberLookup(TestCase):
134+
"""
135+
Test filtering queryset on composite type members.
136+
"""
137+
138+
def test_value(self):
139+
"""Test finding a record by composite member value."""
140+
t = SimpleType(a=1, b="β ☃", c=datetime.datetime(1985, 10, 26, 9, 0))
141+
m = SimpleModel(test_field=t)
142+
m.save()
143+
144+
self.assertEqual(SimpleModel.objects.get(test_field__a=1), m)
145+
146+
def test_comparison(self):
147+
"""Test finding a record by comparison on a composite member value."""
148+
t = SimpleType(a=1, b="β ☃", c=datetime.datetime(1985, 10, 26, 9, 0))
149+
m = SimpleModel(test_field=t)
150+
m.save()
151+
t.a = 3
152+
SimpleModel.objects.create(test_field=t)
153+
154+
self.assertEqual(SimpleModel.objects.get(test_field__a__lt=2), m)
155+
156+
def test_renamed(self):
157+
"""Test finding a record by composite member value with a different ORM name."""
158+
t = RenamedMemberType(orm_name="foo")
159+
m = RenamedMemberModel(field=t)
160+
m.save()
161+
162+
self.assertEqual(RenamedMemberModel.objects.get(field__orm_name="foo"), m)

0 commit comments

Comments
 (0)