mirror of
https://github.com/jazzband/django-eav2.git
synced 2026-03-16 22:40:26 +00:00
Added documentation and tests
This commit is contained in:
parent
9a5e3574e1
commit
39e6a21403
2 changed files with 98 additions and 4 deletions
25
managers.py
25
managers.py
|
|
@ -5,16 +5,23 @@ from django.db import models
|
|||
from .models import EavAttribute, EavValue
|
||||
|
||||
def eav_filter(func):
|
||||
'''
|
||||
Decorator used to wrap filter and exlclude methods. Passes args through
|
||||
expand_q_filters and kwargs through expand_eav_filter. Returns the
|
||||
called function (filter or exclude) .distinct()
|
||||
'''
|
||||
@wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
new_args = []
|
||||
for arg in args:
|
||||
if isinstance(arg, models.Q):
|
||||
# modify Q objects (warning: recursion ahead)
|
||||
new_args.append(expand_q_filters(arg, self.model))
|
||||
arg = expand_q_filters(arg, self.model)
|
||||
new_args.append(arg)
|
||||
|
||||
new_kwargs = {}
|
||||
for key, value in kwargs.items():
|
||||
# modify kwargs (warning: recursion ahead)
|
||||
new_key, new_value = expand_eav_filter(self.model, key, value)
|
||||
new_kwargs.update({new_key: new_value})
|
||||
|
||||
|
|
@ -23,6 +30,11 @@ def eav_filter(func):
|
|||
|
||||
|
||||
def expand_q_filters(q, root_cls):
|
||||
'''
|
||||
Takes a Q object and a model class.
|
||||
Recursivley passes each filter / value in the Q object tree leaf nodes
|
||||
through expand_eav_filter
|
||||
'''
|
||||
new_children = []
|
||||
for qi in q.children:
|
||||
if type(qi) is tuple:
|
||||
|
|
@ -38,6 +50,17 @@ def expand_q_filters(q, root_cls):
|
|||
|
||||
|
||||
def expand_eav_filter(model_cls, key, value):
|
||||
'''
|
||||
Accepts a model class and a key, value.
|
||||
Recurisively replaces any eav filter with a subquery.
|
||||
|
||||
For example:
|
||||
key = 'eav__height'
|
||||
value = 5
|
||||
Would return:
|
||||
key = 'eav_values__in'
|
||||
value = EavValues.objects.filter(value_int=5, attribute__slug='height')
|
||||
'''
|
||||
from .utils import EavRegistry
|
||||
fields = key.split('__')
|
||||
|
||||
|
|
|
|||
|
|
@ -161,10 +161,81 @@ class EavFilterTests(TestCase):
|
|||
|
||||
self.assertEqual(User.objects.exclude(eav__city='Paris').count(), 2)
|
||||
|
||||
#TODO Exclude and EAV Q objects are broken!
|
||||
#self.assertEqual(User.objects.exclude(Q(eav__city='Paris')).count(), 2)
|
||||
|
||||
self.assertEqual(User.objects.filter(Q(eav__city='Paris') & \
|
||||
Q(username='Bob')).count(), 1)
|
||||
|
||||
self.assertEqual(User.objects.filter(Q(eav__city='Paris', username='Jack')).count(), 0)
|
||||
|
||||
def test_you_can_filter_entity_by_q_objects_with_lookups(self):
|
||||
class UserEav(EavConfig):
|
||||
manager_field_name = 'eav_objects'
|
||||
EavRegistry.register(User, UserEav)
|
||||
|
||||
EavAttribute.objects.create(datatype=EavAttribute.TYPE_INT,
|
||||
name='Height')
|
||||
EavAttribute.objects.create(datatype=EavAttribute.TYPE_FLOAT,
|
||||
name='Weight')
|
||||
u = User.objects.create(username='Bob')
|
||||
u.eav.height = 10
|
||||
u.eav.weight = 20
|
||||
u.save()
|
||||
u = User.objects.create(username='Jack')
|
||||
u.eav.height = 20
|
||||
u.eav.weight = 10
|
||||
u.save()
|
||||
u = User.objects.create(username='Fred')
|
||||
u.eav.height = 15
|
||||
u.eav.weight = 15
|
||||
u.save()
|
||||
'''
|
||||
This is what we have now:
|
||||
|
||||
Username Hieght Weight
|
||||
-------- ------ ------
|
||||
Bob 10 20
|
||||
Jack 20 10
|
||||
Fred 15 15
|
||||
'''
|
||||
|
||||
self.assertEqual(User.eav_objects.filter(eav__height__gt=12).count(), 2)
|
||||
self.assertEqual(User.eav_objects.filter(Q(eav__height__gt=12)).count(), 2)
|
||||
self.assertEqual(User.eav_objects.filter(eav__height__gte=20).count(), 1)
|
||||
self.assertEqual(User.eav_objects.filter(Q(eav__height__gte=20)).count(), 1)
|
||||
|
||||
self.assertEqual(User.eav_objects.filter(Q(eav__height__gte=20) & Q(username='Fred')).count(), 0)
|
||||
self.assertEqual(User.eav_objects.filter(Q(eav__height=15) & Q(username='Fred')).count(), 1)
|
||||
|
||||
self.assertEqual(User.eav_objects.filter(eav__height=20, eav__weight=10).count(), 1)
|
||||
|
||||
self.assertEqual(User.eav_objects.filter(Q(eav__height=20) | Q(eav__weight=10) | Q(eav__weight=15)).count(), 2)
|
||||
|
||||
def test_broken_eav_filters(self):
|
||||
EavRegistry.register(User)
|
||||
|
||||
EavAttribute.objects.create(datatype=EavAttribute.TYPE_INT,
|
||||
name='Height')
|
||||
EavAttribute.objects.create(datatype=EavAttribute.TYPE_FLOAT,
|
||||
name='Weight')
|
||||
u = User.objects.create(username='Bob')
|
||||
u.eav.height = 10
|
||||
u.eav.weight = 20
|
||||
u.eav.city = 'Paris'
|
||||
u.eav.country = 'France'
|
||||
u.save()
|
||||
u = User.objects.create(username='Jack')
|
||||
u.eav.height = 20
|
||||
u.eav.weight = 10
|
||||
u.eav.city = 'New York'
|
||||
u.eav.country = 'Paris'
|
||||
u.save()
|
||||
u = User.objects.create(username='Fred')
|
||||
u.eav.height = 15
|
||||
u.eav.weight = 15
|
||||
u.eav.city = 'Georgetown'
|
||||
u.eav.country = 'Guyana'
|
||||
u.save()
|
||||
|
||||
self.assertEqual(User.objects.exclude(Q(eav__city='Paris')).count(), 2)
|
||||
self.assertEqual(User.objects.filter(Q(eav__height=20) & Q(eav__weight=10)).count(), 1)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue