Merge branch 'django110'

fix_request_path_info
Diederik van der Boor 2016-08-10 13:55:37 +02:00
commit cf1d4b532d
6 changed files with 190 additions and 132 deletions

View File

@ -15,6 +15,7 @@ env:
- DJANGO="Django>=1.7,<1.8" - DJANGO="Django>=1.7,<1.8"
- DJANGO="Django>=1.8,<1.9" - DJANGO="Django>=1.8,<1.9"
- DJANGO="Django>=1.9,<1.10" - DJANGO="Django>=1.9,<1.10"
- DJANGO="Django>=1.10,<1.11"
- DJANGO="https://github.com/django/django/tarball/master" - DJANGO="https://github.com/django/django/tarball/master"
matrix: matrix:
@ -32,16 +33,22 @@ matrix:
env: DJANGO="Django>=1.4,<1.5" env: DJANGO="Django>=1.4,<1.5"
- python: "3.4" - python: "3.4"
env: DJANGO="Django>=1.9,<1.10" env: DJANGO="Django>=1.9,<1.10"
- python: "3.4"
env: DJANGO="Django>=1.10,<1.11"
- python: "3.3" - python: "3.3"
env: DJANGO="Django>=1.4,<1.5" env: DJANGO="Django>=1.4,<1.5"
- python: "3.3" - python: "3.3"
env: DJANGO="Django>=1.9,<1.10" env: DJANGO="Django>=1.9,<1.10"
- python: "3.3"
env: DJANGO="Django>=1.10,<1.11"
- python: "3.2" - python: "3.2"
env: DJANGO="Django>=1.4,<1.5" env: DJANGO="Django>=1.4,<1.5"
- python: "3.2" - python: "3.2"
env: DJANGO="Django>=1.9,<1.10" env: DJANGO="Django>=1.9,<1.10"
- python: "3.2"
env: DJANGO="Django>=1.10,<1.11"
- python: "2.6" - python: "2.6"
env: DJANGO="Django>=1.7,<1.8" env: DJANGO="Django>=1.7,<1.8"
@ -49,6 +56,8 @@ matrix:
env: DJANGO="Django>=1.8,<1.9" env: DJANGO="Django>=1.8,<1.9"
- python: "2.6" - python: "2.6"
env: DJANGO="Django>=1.9,<1.10" env: DJANGO="Django>=1.9,<1.10"
- python: "2.6"
env: DJANGO="Django>=1.10,<1.11"
- python: "2.6" - python: "2.6"
env: DJANGO="https://github.com/django/django/tarball/master" env: DJANGO="https://github.com/django/django/tarball/master"
allow_failures: allow_failures:

View File

@ -71,6 +71,7 @@ class PolymorphicModelBase(ModelBase):
self.validate_model_fields(new_class) self.validate_model_fields(new_class)
# create list of all managers to be inherited from the base classes # create list of all managers to be inherited from the base classes
if django.VERSION < (1, 10):
inherited_managers = new_class.get_inherited_managers(attrs) inherited_managers = new_class.get_inherited_managers(attrs)
# add the managers to the new model # add the managers to the new model
@ -105,6 +106,7 @@ class PolymorphicModelBase(ModelBase):
return new_class return new_class
if django.VERSION < (1, 10):
def get_inherited_managers(self, attrs): def get_inherited_managers(self, attrs):
""" """
Return list of all managers to be inherited/propagated from the base classes; Return list of all managers to be inherited/propagated from the base classes;

View File

@ -4,6 +4,7 @@
""" """
from __future__ import absolute_import from __future__ import absolute_import
import copy
import django import django
from django.db import models from django.db import models
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -100,7 +101,9 @@ def translate_polymorphic_filter_definitions_in_args(queryset_model, args, using
Returns: modified Q objects Returns: modified Q objects
""" """
if django.VERSION >= (1, 6): if django.VERSION >= (1, 10):
q_objects = [copy.deepcopy(q) for q in args]
elif django.VERSION >= (1, 6):
q_objects = [q.clone() for q in args] q_objects = [q.clone() for q in args]
else: else:
q_objects = args # NOTE: edits existing objects in place. q_objects = args # NOTE: edits existing objects in place.

View File

@ -1,9 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import django
import re
from django.db import models from django.db import models
from django.utils import six from django.utils import six
try:
from django.utils.six import python_2_unicode_compatible
except ImportError:
from django.utils.encoding import python_2_unicode_compatible # Django 1.5
RE_DEFERRED = re.compile('_Deferred_.*')
@python_2_unicode_compatible
class ShowFieldBase(object): class ShowFieldBase(object):
""" base class for the ShowField... model mixins, does the work """ """ base class for the ShowField... model mixins, does the work """
@ -11,6 +20,7 @@ class ShowFieldBase(object):
polymorphic_showfield_type = False polymorphic_showfield_type = False
polymorphic_showfield_content = False polymorphic_showfield_content = False
polymorphic_showfield_deferred = False
# these may be overridden by the user # these may be overridden by the user
polymorphic_showfield_max_line_width = None polymorphic_showfield_max_line_width = None
@ -87,12 +97,12 @@ class ShowFieldBase(object):
parts.append((False, out, ',')) parts.append((False, out, ','))
def __unicode__(self): def __str__(self):
# create list ("parts") containing one tuple for each title/field: # create list ("parts") containing one tuple for each title/field:
# ( bool: new section , item-text , separator to use after item ) # ( bool: new section , item-text , separator to use after item )
# start with model name # start with model name
parts = [(True, self.__class__.__name__, ':')] parts = [(True, RE_DEFERRED.sub('', self.__class__.__name__), ':')]
# add all regular fields # add all regular fields
self._showfields_add_regular_fields(parts) self._showfields_add_regular_fields(parts)
@ -105,6 +115,11 @@ class ShowFieldBase(object):
if hasattr(self, 'polymorphic_extra_select_names'): if hasattr(self, 'polymorphic_extra_select_names'):
self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts) self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts)
if self.polymorphic_showfield_deferred:
fields = self.get_deferred_fields()
if fields:
parts.append((False, u"deferred[{0}]".format(",".join(sorted(fields))), ''))
# format result # format result
indent = len(self.__class__.__name__) + 5 indent = len(self.__class__.__name__) + 5
@ -142,6 +157,11 @@ class ShowFieldBase(object):
return '<' + out + '>' return '<' + out + '>'
if django.VERSION < (1, 8):
def get_deferred_fields(self):
from django.db.models.query_utils import DeferredAttribute
return set(attr for attr, value in self.__class__.__dict__.items() if isinstance(value, DeferredAttribute))
class ShowFieldType(ShowFieldBase): class ShowFieldType(ShowFieldBase):
""" model mixin that shows the object's class and it's field types """ """ model mixin that shows the object's class and it's field types """

View File

@ -46,6 +46,7 @@ class PlainC(PlainB):
class Model2A(ShowFieldType, PolymorphicModel): class Model2A(ShowFieldType, PolymorphicModel):
field1 = models.CharField(max_length=10) field1 = models.CharField(max_length=10)
polymorphic_showfield_deferred = True
class Model2B(Model2A): class Model2B(Model2A):
@ -562,18 +563,19 @@ class PolymorphicTests(TestCase):
self.create_model2abcd() self.create_model2abcd()
objects_deferred = Model2A.objects.defer('field1') objects_deferred = Model2A.objects.defer('field1')
self.assertNotIn('field1', objects_deferred[0].__dict__,
'field1 was not deferred (using defer())') self.assertNotIn('field1', objects_deferred[0].__dict__, 'field1 was not deferred (using defer())')
self.assertEqual(repr(objects_deferred[0]), self.assertEqual(repr(objects_deferred[0]),
'<Model2A_Deferred_field1: id 1, field1 (CharField)>') '<Model2A: id 1, field1 (CharField), deferred[field1]>')
self.assertEqual(repr(objects_deferred[1]), self.assertEqual(repr(objects_deferred[1]),
'<Model2B_Deferred_field1: id 2, field1 (CharField), field2 (CharField)>') '<Model2B: id 2, field1 (CharField), field2 (CharField), deferred[field1]>')
self.assertEqual(repr(objects_deferred[2]), self.assertEqual(repr(objects_deferred[2]),
'<Model2C_Deferred_field1: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>') '<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField), deferred[field1]>')
self.assertEqual(repr(objects_deferred[3]), self.assertEqual(repr(objects_deferred[3]),
'<Model2D_Deferred_field1: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)>') '<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField), deferred[field1]>')
objects_only = Model2A.objects.only('pk', 'polymorphic_ctype', 'field1') objects_only = Model2A.objects.only('pk', 'polymorphic_ctype', 'field1')
self.assertIn('field1', objects_only[0].__dict__, self.assertIn('field1', objects_only[0].__dict__,
'qs.only("field1") was used, but field1 was incorrectly deferred') 'qs.only("field1") was used, but field1 was incorrectly deferred')
self.assertIn('field1', objects_only[3].__dict__, self.assertIn('field1', objects_only[3].__dict__,
@ -584,14 +586,13 @@ class PolymorphicTests(TestCase):
self.assertEqual(repr(objects_only[0]), self.assertEqual(repr(objects_only[0]),
'<Model2A: id 1, field1 (CharField)>') '<Model2A: id 1, field1 (CharField)>')
self.assertEqual(repr(objects_only[1]), self.assertEqual(repr(objects_only[1]),
'<Model2B_Deferred_field2: ' '<Model2B: id 2, field1 (CharField), field2 (CharField), deferred[field2]>')
'id 2, field1 (CharField), field2 (CharField)>')
self.assertEqual(repr(objects_only[2]), self.assertEqual(repr(objects_only[2]),
'<Model2C_Deferred_field2_field3_model2a_ptr_id: ' '<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField), '
'id 3, field1 (CharField), field2 (CharField), field3 (CharField)>') 'deferred[field2,field3,model2a_ptr_id]>')
self.assertEqual(repr(objects_only[3]), self.assertEqual(repr(objects_only[3]),
'<Model2D_Deferred_field2_field3_field4_model2a_ptr_id_model2b_ptr_id: ' '<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField), '
'id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)>') 'deferred[field2,field3,field4,model2a_ptr_id,model2b_ptr_id]>')
# A bug in Django 1.4 prevents using defer across reverse relations # A bug in Django 1.4 prevents using defer across reverse relations
# <https://code.djangoproject.com/ticket/14694>. Since polymorphic # <https://code.djangoproject.com/ticket/14694>. Since polymorphic
@ -611,7 +612,7 @@ class PolymorphicTests(TestCase):
self.assertEqual(repr(objects_deferred_field4[2]), self.assertEqual(repr(objects_deferred_field4[2]),
'<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>') '<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>')
self.assertEqual(repr(objects_deferred_field4[3]), self.assertEqual(repr(objects_deferred_field4[3]),
'<Model2D_Deferred_field4: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)>') '<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField), deferred[field4]>')
objects_only_field4 = Model2A.objects.only( objects_only_field4 = Model2A.objects.only(
'polymorphic_ctype', 'field1', 'polymorphic_ctype', 'field1',
@ -625,7 +626,7 @@ class PolymorphicTests(TestCase):
self.assertEqual(repr(objects_only_field4[2]), self.assertEqual(repr(objects_only_field4[2]),
'<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>') '<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>')
self.assertEqual(repr(objects_only_field4[3]), self.assertEqual(repr(objects_only_field4[3]),
'<Model2D_Deferred_field4: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)>') '<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField), deferred[field4]>')
def test_manual_get_real_instance(self): def test_manual_get_real_instance(self):
@ -681,17 +682,26 @@ class PolymorphicTests(TestCase):
self.assertEqual(show_base_manager(PlainC), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainC'>") self.assertEqual(show_base_manager(PlainC), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainC'>")
self.assertEqual(show_base_manager(Model2A), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.Model2A'>") self.assertEqual(show_base_manager(Model2A), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.Model2A'>")
if django.VERSION >= (1, 10):
# The new inheritance makes all model levels polymorphic
self.assertEqual(show_base_manager(Model2B), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.Model2B'>")
self.assertEqual(show_base_manager(Model2C), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.Model2C'>")
else:
self.assertEqual(show_base_manager(Model2B), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2B'>") self.assertEqual(show_base_manager(Model2B), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2B'>")
self.assertEqual(show_base_manager(Model2C), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2C'>") self.assertEqual(show_base_manager(Model2C), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2C'>")
self.assertEqual(show_base_manager(One2OneRelatingModel), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.One2OneRelatingModel'>") self.assertEqual(show_base_manager(One2OneRelatingModel), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.One2OneRelatingModel'>")
if django.VERSION >= (1, 10):
# The new inheritance makes all model levels polymorphic
self.assertEqual(show_base_manager(One2OneRelatingModelDerived), "<class 'polymorphic.managers.PolymorphicManager'> <class 'polymorphic.tests.One2OneRelatingModelDerived'>")
else:
self.assertEqual(show_base_manager(One2OneRelatingModelDerived), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.One2OneRelatingModelDerived'>") self.assertEqual(show_base_manager(One2OneRelatingModelDerived), "<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.One2OneRelatingModelDerived'>")
def test_instance_default_manager(self): def test_instance_default_manager(self):
def show_default_manager(instance): def show_default_manager(instance):
return "{0} {1}".format( return "{0} {1}".format(
repr(type(instance._default_manager)), repr(type(instance.__class__._default_manager)),
repr(instance._default_manager.model) repr(instance.__class__._default_manager.model)
) )
plain_a = PlainA(field1='C1') plain_a = PlainA(field1='C1')
@ -757,7 +767,7 @@ class PolymorphicTests(TestCase):
# no pretty printing # no pretty printing
ModelShow1_plain.objects.create(field1='abc') ModelShow1_plain.objects.create(field1='abc')
ModelShow2_plain.objects.create(field1='abc', field2='def') ModelShow2_plain.objects.create(field1='abc', field2='def')
self.assertEqual(repr(ModelShow1_plain.objects.all()), '[<ModelShow1_plain: ModelShow1_plain object>, <ModelShow2_plain: ModelShow2_plain object>]') self.assertEqual(qrepr(ModelShow1_plain.objects.all()), '<QuerySet [<ModelShow1_plain: ModelShow1_plain object>, <ModelShow2_plain: ModelShow2_plain object>]>')
def test_extra_method(self): def test_extra_method(self):
self.create_model2abcd() self.create_model2abcd()
@ -1138,10 +1148,11 @@ class PolymorphicTests(TestCase):
self.assertEqual(result, {'cnt': 2}) self.assertEqual(result, {'cnt': 2})
# aggregate using **args # aggregate using **args
with self.assertRaisesMessage(AssertionError, 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only'): self.assertRaisesMessage(
Model2A.objects.aggregate(Count('Model2B___field2')) AssertionError,
'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only',
lambda: Model2A.objects.aggregate(Count('Model2B___field2'))
)
@skipIf(django.VERSION < (1,8,), "This test needs Django >=1.8") @skipIf(django.VERSION < (1,8,), "This test needs Django >=1.8")
def test_polymorphic__complex_aggregate(self): def test_polymorphic__complex_aggregate(self):
@ -1172,11 +1183,10 @@ class PolymorphicTests(TestCase):
@skipIf(django.VERSION < (1,8,), "This test needs Django >=1.8") @skipIf(django.VERSION < (1,8,), "This test needs Django >=1.8")
def test_polymorphic__expressions(self): def test_polymorphic__expressions(self):
from django.db.models.expressions import DateTime from django.db.models.functions import Concat
from django.utils.timezone import utc
# no exception raised # no exception raised
result = DateModel.objects.annotate(val=DateTime('date', 'day', utc)) result = Model2B.objects.annotate(val=Concat('field1', 'field2'))
self.assertEqual(list(result), []) self.assertEqual(list(result), [])
class RegressionTests(TestCase): class RegressionTests(TestCase):
@ -1288,3 +1298,16 @@ class MultipleDatabasesTests(TestCase):
# Ensure no queries are made using the default database. # Ensure no queries are made using the default database.
self.assertNumQueries(0, func) self.assertNumQueries(0, func)
def qrepr(data):
"""
Ensure consistent repr() output for the QuerySet object.
"""
if isinstance(data, QuerySet):
if django.VERSION >= (1, 10):
return repr(data)
else:
return '<QuerySet %r>' % data
return repr(data)

View File

@ -1,11 +1,11 @@
[tox] [tox]
envlist= envlist=
py26-django{14,15,16}, py26-django{14,15,16},
py27-django{14,15,16,17,18,19}, py27-django{14,15,16,17,18,19,110},
py32-django{15,16,17,18}, py32-django{15,16,17,18},
py33-django{15,16,17,18}, py33-django{15,16,17,18},
py34-django{15,16,17,18,19}, py34-django{15,16,17,18,19,110},
py35-django{18,19} py35-django{18,19,110}
# py33-django-dev, # py33-django-dev,
docs, docs,
@ -17,6 +17,7 @@ deps =
django17: Django >= 1.7, < 1.8 django17: Django >= 1.7, < 1.8
django18: Django >= 1.8, < 1.9 django18: Django >= 1.8, < 1.9
django19: Django >= 1.9, < 1.10 django19: Django >= 1.9, < 1.10
django110: Django >= 1.10, < 1.11
django-dev: https://github.com/django/django/tarball/master django-dev: https://github.com/django/django/tarball/master
commands= commands=
python runtests.py python runtests.py