diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/modeltests/defer/__init__.py | 0 | ||||
| -rw-r--r-- | tests/modeltests/defer/models.py | 89 | ||||
| -rw-r--r-- | tests/regressiontests/queries/models.py | 6 |
3 files changed, 95 insertions, 0 deletions
diff --git a/tests/modeltests/defer/__init__.py b/tests/modeltests/defer/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/modeltests/defer/__init__.py diff --git a/tests/modeltests/defer/models.py b/tests/modeltests/defer/models.py new file mode 100644 index 0000000000..1f515bc95e --- /dev/null +++ b/tests/modeltests/defer/models.py @@ -0,0 +1,89 @@ +""" +Tests for defer() and only(). +""" + +from django.db import models +from django.db.models.query_utils import DeferredAttribute + +class Secondary(models.Model): + first = models.CharField(max_length=50) + second = models.CharField(max_length=50) + +class Primary(models.Model): + name = models.CharField(max_length=50) + value = models.CharField(max_length=50) + related = models.ForeignKey(Secondary) + +def count_delayed_fields(obj, debug=False): + """ + Returns the number of delayed attributes on the given model instance. + """ + count = 0 + for field in obj._meta.fields: + if isinstance(obj.__class__.__dict__.get(field.attname), + DeferredAttribute): + if debug: + print field.name, field.attname + count += 1 + return count + + +__test__ = {"API_TEST": """ +To all outward appearances, instances with deferred fields look the same as +normal instances when we examine attribut values. Therefore we test for the +number of deferred fields on returned instances (by poking at the internals), +as a way to observe what is going on. + +>>> s1 = Secondary.objects.create(first="x1", second="y1") +>>> p1 = Primary.objects.create(name="p1", value="xx", related=s1) + +>>> qs = Primary.objects.all() + +>>> count_delayed_fields(qs.defer('name')[0]) +1 +>>> count_delayed_fields(qs.only('name')[0]) +2 +>>> count_delayed_fields(qs.defer('related__first')[0]) +0 +>>> obj = qs.select_related().only('related__first')[0] +>>> count_delayed_fields(obj) +2 +>>> obj.related_id == s1.pk +True +>>> count_delayed_fields(qs.defer('name').extra(select={'a': 1})[0]) +1 +>>> count_delayed_fields(qs.extra(select={'a': 1}).defer('name')[0]) +1 +>>> count_delayed_fields(qs.defer('name').defer('value')[0]) +2 +>>> count_delayed_fields(qs.only('name').only('value')[0]) +2 +>>> count_delayed_fields(qs.only('name').defer('value')[0]) +2 +>>> count_delayed_fields(qs.only('name', 'value').defer('value')[0]) +2 +>>> count_delayed_fields(qs.defer('name').only('value')[0]) +2 +>>> obj = qs.only()[0] +>>> count_delayed_fields(qs.defer(None)[0]) +0 +>>> count_delayed_fields(qs.only('name').defer(None)[0]) +0 + +User values() won't defer anything (you get the full list of dictionaries +back), but it still works. +>>> qs.defer('name').values()[0] == {'id': p1.id, 'name': u'p1', 'value': 'xx', 'related_id': s1.id} +True +>>> qs.only('name').values()[0] == {'id': p1.id, 'name': u'p1', 'value': 'xx', 'related_id': s1.id} +True + +Using defer() and only() with get() is also valid. +>>> count_delayed_fields(qs.defer('name').get(pk=p1.pk)) +1 +>>> count_delayed_fields(qs.only('name').get(pk=p1.pk)) +2 + +# KNOWN NOT TO WORK: >>> count_delayed_fields(qs.only('name').select_related('related')[0]) +# KNOWN NOT TO WORK >>> count_delayed_fields(qs.defer('related').select_related('related')[0]) + +"""} diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py index ccf06be5f3..939fc0e86f 100644 --- a/tests/regressiontests/queries/models.py +++ b/tests/regressiontests/queries/models.py @@ -890,6 +890,12 @@ unpickling. >>> query2.as_sql()[0] == query True +Check pickling of deferred-loading querysets +>>> qs = Item.objects.defer('name', 'creator') +>>> q2 = pickle.loads(pickle.dumps(qs)) +>>> list(qs) == list(q2) +True + Bug #7277 >>> n1.annotation_set.filter(Q(tag=t5) | Q(tag__children=t5) | Q(tag__children__children=t5)) [<Annotation: a1>] |
