diff --git a/.travis.yml b/.travis.yml index 78118db..78ac7e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ env: - DJANGO=django==1.5 - DJANGO=django==1.6 - DJANGO=django==1.7 + - DJANGO=https://www.djangoproject.com/download/1.8a1/tarball/ #- DJANGO=https://github.com/django/django/archive/stable/1.6.x.zip matrix: @@ -19,6 +20,8 @@ matrix: env: DJANGO=django==1.4.5 - python: "2.6" env: DJANGO=django==1.7 + - python: "2.6" + env: DJANGO=https://www.djangoproject.com/download/1.8a1/tarball/ install: - pip install $DJANGO coverage==3.6 diff --git a/polymorphic/query.py b/polymorphic/query.py index 35d091a..eab634e 100644 --- a/polymorphic/query.py +++ b/polymorphic/query.py @@ -6,6 +6,7 @@ from __future__ import absolute_import from collections import defaultdict +import django from django.db.models.query import QuerySet from django.contrib.contenttypes.models import ContentType from django.utils import six @@ -95,10 +96,22 @@ class PolymorphicQuerySet(QuerySet): def _process_aggregate_args(self, args, kwargs): """for aggregate and annotate kwargs: allow ModelX___field syntax for kwargs, forbid it for args. Modifies kwargs if needed (these are Aggregate objects, we translate the lookup member variable)""" + + def patch_lookup(a): + if django.VERSION < (1, 8): + a.lookup = translate_polymorphic_field_path(self.model, a.lookup) + else: + # With Django > 1.8, the field on which the aggregate operates is + # stored inside a query expression. + a.source_expressions[0].name = translate_polymorphic_field_path( + self.model, a.source_expressions[0].name) + + get_lookup = lambda a: a.lookup if django.VERSION < (1, 8) else a.source_expressions[0].name + for a in args: - assert not '___' in a.lookup, 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only' + assert '___' not in get_lookup(a), 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only' for a in six.itervalues(kwargs): - a.lookup = translate_polymorphic_field_path(self.model, a.lookup) + patch_lookup(a) def annotate(self, *args, **kwargs): """translate the polymorphic field paths in the kwargs, then call vanilla annotate. diff --git a/polymorphic/query_translate.py b/polymorphic/query_translate.py index b6ee8cc..4008e61 100644 --- a/polymorphic/query_translate.py +++ b/polymorphic/query_translate.py @@ -7,7 +7,15 @@ from __future__ import absolute_import from django.db import models from django.contrib.contenttypes.models import ContentType from django.db.models import Q, FieldDoesNotExist -from django.db.models.related import RelatedObject + +try: + from django.db.models.related import RelatedObject +except ImportError: + # django.db.models.related.RelatedObject was replaced + # by django.db.models.fields.related.ForeignObjectRel in + # Django 1.8 + from django.db.models.fields.related import ForeignObjectRel + RelatedObject = ForeignObjectRel from functools import reduce diff --git a/tox.ini b/tox.ini index a642ae1..dc4c278 100644 --- a/tox.ini +++ b/tox.ini @@ -8,14 +8,17 @@ envlist= py27-django15, py27-django16, py27-django17, + py27-django18, py32-django15, py32-django16, py32-django17, + py32-django18, py33-django15, py33-django16, py33-django17, + py33-django18, py33-django-dev, docs, @@ -61,6 +64,11 @@ basepython=python2.7 deps= django==1.7 +[testenv:py27-django18] +basepython=python2.7 +deps= + https://www.djangoproject.com/download/1.8a1/tarball/ + [testenv:py32-django15] basepython=python3.2 deps= @@ -76,6 +84,11 @@ basepython=python3.2 deps= django==1.7 +[testenv:py32-django18] +basepython=python3.2 +deps= + https://www.djangoproject.com/download/1.8a1/tarball/ + [testenv:py33-django15] basepython=python3.3 deps= @@ -91,6 +104,11 @@ basepython=python3.3 deps= django==1.7 +[testenv:py33-django18] +basepython=python3.3 +deps= + https://www.djangoproject.com/download/1.8a1/tarball/ + [testenv:py33-django-dev] basepython=python3.3 deps=