Ticket #11707: limit_ForeignKey.trunk.patch
File limit_ForeignKey.trunk.patch, 5.2 KB (added by , 13 years ago) |
---|
-
django/forms/models.py
diff -r 38c339d6093d django/forms/models.py
a b 879 879 yield (u"", self.field.empty_label) 880 880 if self.field.cache_choices: 881 881 if self.field.choice_cache is None: 882 self.field.choice_cache = [ 883 self.choice(obj) for obj in self.queryset.all() 884 ] 882 self.field.choice_cache = list(self.distinct_choices()) 885 883 for choice in self.field.choice_cache: 886 884 yield choice 887 885 else: 888 for obj in self.queryset.all(): 886 for choice in self.distinct_choices(): 887 yield choice 888 889 def distinct_choices(self): 890 """Yields a choice for each distinct object in the queryset. 891 892 If you use limit_choices_to you could have more than one results for a 893 single Instance. DISTINCT in the db won't work as expected so we do 894 the check here.""" 895 seen_choices = set() 896 for obj in self.queryset.all(): 897 if obj.pk not in seen_choices: 898 seen_choices.add(obj.pk) 889 899 yield self.choice(obj) 890 900 891 901 def __len__(self): … … 975 985 return None 976 986 try: 977 987 key = self.to_field_name or 'pk' 978 value = self.queryset.get(**{key: value}) 988 values = self.queryset.filter(**{key: value}) 989 # If you use limit_choices_to you could have more than one results 990 # for a single Instance. DISTINCT in the db won't work as expected 991 # so we do the check here. 992 if not values: 993 raise self.queryset.model.DoesNotExist 994 if len(values) == 1: 995 value = values[0] 996 else: 997 pks = set(value.pk for value in values) 998 if len(pks) == 1: 999 value = values[0] 1000 else: 1001 raise self.queryset.model.MultipleObjectsReturned 979 1002 except (ValueError, self.queryset.model.DoesNotExist): 980 1003 raise ValidationError(self.error_messages['invalid_choice']) 981 1004 return value -
tests/regressiontests/model_fields/models.py
diff -r 38c339d6093d tests/regressiontests/model_fields/models.py
a b 29 29 b = models.CharField(max_length=10) 30 30 a = models.ForeignKey(Foo, default=get_foo) 31 31 32 class Baz(models.Model): 33 a = models.CharField(max_length=5) 34 #Only Foos related to Bars starting with 'a' 35 foo = models.ForeignKey(Foo, limit_choices_to=models.Q(bar__b__startswith='a')) 36 32 37 class Whiz(models.Model): 33 38 CHOICES = ( 34 39 ('Group 1', ( -
tests/regressiontests/model_fields/tests.py
diff -r 38c339d6093d tests/regressiontests/model_fields/tests.py
a b 1 1 import datetime 2 2 from decimal import Decimal 3 import re 3 4 4 5 from django import test 5 6 from django import forms … … 8 9 from django.db.models.fields.files import FieldFile 9 10 from django.utils import unittest 10 11 11 from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document, RenamedField12 from models import Foo, Bar, Baz, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document, RenamedField 12 13 13 14 # If PIL available, do these tests. 14 15 if Image: … … 109 110 # This should not crash. That counts as a win for our purposes. 110 111 Foo.objects.filter(d__gte=100000000000) 111 112 113 114 class BazForm(forms.ModelForm): 115 class Meta: 116 model = Baz 117 118 112 119 class ForeignKeyTests(test.TestCase): 113 120 def test_callable_default(self): 114 121 """Test the use of a lazy callable for ForeignKey.default""" … … 116 123 b = Bar.objects.create(b="bcd") 117 124 self.assertEqual(b.a, a) 118 125 126 def test_distinct_choice_limit(self): 127 """Doesn't make sense to offer the same ForeignKey multiple times in a form""" 128 a = Foo.objects.create(a='a', d=Decimal("-1")) 129 b = Foo.objects.create(a='b', d=Decimal("1")) 130 Bar.objects.create(b='ah', a=a) 131 Bar.objects.create(b='aha', a=a) 132 Bar.objects.create(b='bla', a=b) 133 form = BazForm() 134 fk_field = str(form['foo']) 135 self.assertEqual(len(re.findall(r'value="%s"' % b.pk, fk_field)), 0) 136 self.assertEqual(len(re.findall(r'value="%s"' % a.pk, fk_field)), 1) 137 138 def test_distinct_choice_limit_save(self): 139 """Doesn't make sense to offer the same ForeignKey multiple times in a form""" 140 a = Foo.objects.create(a='a', d=Decimal("-1")) 141 b = Foo.objects.create(a='b', d=Decimal("1")) 142 Bar.objects.create(b='ah', a=a) 143 Bar.objects.create(b='aha', a=a) 144 Bar.objects.create(b='bla', a=b) 145 form = BazForm({'foo': a.pk, 'a': 'a'}) 146 self.assertTrue(form.is_valid()) 147 obj = form.save() 148 self.assertEqual(obj.foo.pk, a.pk) 149 119 150 class DateTimeFieldTests(unittest.TestCase): 120 151 def test_datetimefield_to_python_usecs(self): 121 152 """DateTimeField.to_python should support usecs"""