diff options
author | Niclas Olofsson <n@niclasolofsson.se> | 2014-12-04 21:47:48 +0100 |
---|---|---|
committer | Tim Graham <timograham@gmail.com> | 2014-12-24 14:54:30 -0500 |
commit | 3daa9d60be6672841ceed5bb812b6fb25950dc16 (patch) | |
tree | 1771ecd7ab15fd5795bb605c9d7e710ed0b86935 /tests/select_related | |
parent | b27db97b236569d059fa824c3078e06adf8b4fae (diff) | |
download | django-3daa9d60be6672841ceed5bb812b6fb25950dc16.tar.gz |
Fixed #10414 -- Made select_related() fail on invalid field names.
Diffstat (limited to 'tests/select_related')
-rw-r--r-- | tests/select_related/models.py | 41 | ||||
-rw-r--r-- | tests/select_related/tests.py | 56 |
2 files changed, 96 insertions, 1 deletions
diff --git a/tests/select_related/models.py b/tests/select_related/models.py index 13170e7e69..96aace6a48 100644 --- a/tests/select_related/models.py +++ b/tests/select_related/models.py @@ -10,6 +10,9 @@ the select-related behavior will traverse. from django.db import models from django.utils.encoding import python_2_unicode_compatible +from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation +from django.contrib.contenttypes.models import ContentType + # Who remembers high school biology? @@ -94,3 +97,41 @@ class HybridSpecies(models.Model): def __str__(self): return self.name + + +@python_2_unicode_compatible +class Topping(models.Model): + name = models.CharField(max_length=30) + + def __str__(self): + return self.name + + +@python_2_unicode_compatible +class Pizza(models.Model): + name = models.CharField(max_length=100) + toppings = models.ManyToManyField(Topping) + + def __str__(self): + return self.name + + +@python_2_unicode_compatible +class TaggedItem(models.Model): + tag = models.CharField(max_length=30) + + content_type = models.ForeignKey(ContentType, related_name='select_related_tagged_items') + object_id = models.PositiveIntegerField() + content_object = GenericForeignKey('content_type', 'object_id') + + def __str__(self): + return self.tag + + +@python_2_unicode_compatible +class Bookmark(models.Model): + url = models.URLField() + tags = GenericRelation(TaggedItem) + + def __str__(self): + return self.url diff --git a/tests/select_related/tests.py b/tests/select_related/tests.py index 6b029fa64b..378c0bf992 100644 --- a/tests/select_related/tests.py +++ b/tests/select_related/tests.py @@ -1,8 +1,12 @@ from __future__ import unicode_literals from django.test import TestCase +from django.core.exceptions import FieldError -from .models import Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species, HybridSpecies +from .models import ( + Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species, HybridSpecies, + Pizza, TaggedItem, Bookmark, +) class SelectRelatedTests(TestCase): @@ -126,6 +130,12 @@ class SelectRelatedTests(TestCase): orders = [o.genus.family.order.name for o in world] self.assertEqual(orders, ['Agaricales']) + def test_single_related_field(self): + with self.assertNumQueries(1): + species = Species.objects.select_related('genus__name') + names = [s.genus.name for s in species] + self.assertEqual(sorted(names), ['Amanita', 'Drosophila', 'Homo', 'Pisum']) + def test_field_traversal(self): with self.assertNumQueries(1): s = (Species.objects.all() @@ -152,3 +162,47 @@ class SelectRelatedTests(TestCase): obj = queryset[0] self.assertEqual(obj.parent_1, parent_1) self.assertEqual(obj.parent_2, parent_2) + + +class SelectRelatedValidationTests(TestCase): + """ + select_related() should thrown an error on fields that do not exist and + non-relational fields. + """ + non_relational_error = "Non-relational field given in select_related: '%s'. Choices are: %s" + invalid_error = "Invalid field name(s) given in select_related: '%s'. Choices are: %s" + + def test_non_relational_field(self): + with self.assertRaisesMessage(FieldError, self.non_relational_error % ('name', 'genus')): + list(Species.objects.select_related('name__some_field')) + + with self.assertRaisesMessage(FieldError, self.non_relational_error % ('name', 'genus')): + list(Species.objects.select_related('name')) + + with self.assertRaisesMessage(FieldError, self.non_relational_error % ('name', '(none)')): + list(Domain.objects.select_related('name')) + + def test_many_to_many_field(self): + with self.assertRaisesMessage(FieldError, self.invalid_error % ('toppings', '(none)')): + list(Pizza.objects.select_related('toppings')) + + def test_reverse_relational_field(self): + with self.assertRaisesMessage(FieldError, self.invalid_error % ('child_1', 'genus')): + list(Species.objects.select_related('child_1')) + + def test_invalid_field(self): + with self.assertRaisesMessage(FieldError, self.invalid_error % ('invalid_field', 'genus')): + list(Species.objects.select_related('invalid_field')) + + with self.assertRaisesMessage(FieldError, self.invalid_error % ('related_invalid_field', 'family')): + list(Species.objects.select_related('genus__related_invalid_field')) + + with self.assertRaisesMessage(FieldError, self.invalid_error % ('invalid_field', '(none)')): + list(Domain.objects.select_related('invalid_field')) + + def test_generic_relations(self): + with self.assertRaisesMessage(FieldError, self.invalid_error % ('tags', '')): + list(Bookmark.objects.select_related('tags')) + + with self.assertRaisesMessage(FieldError, self.invalid_error % ('content_object', 'content_type')): + list(TaggedItem.objects.select_related('content_object')) |