Ticket #11707: limit_ForeignKey.4.patch
File limit_ForeignKey.4.patch, 5.6 KB (added by , 13 years ago) |
---|
-
django/forms/models.py
diff -r 06744e116e42 django/forms/models.py
a b 873 873 self.queryset = field.queryset 874 874 875 875 def __iter__(self): 876 """on the memo dictionary: 877 If you use limit_choices_to you could have more than one results 878 for a single Instance. DISTINCT in the db won't work as expected 879 so we do the check here. If SQL gets fixed remove this. 880 """ 876 881 if self.field.empty_label is not None: 877 882 yield (u"", self.field.empty_label) 878 883 if self.field.cache_choices: 879 884 if self.field.choice_cache is None: 880 self.field.choice_cache = [ 881 self.choice(obj) for obj in self.queryset.all() 882 ] 883 for choice in self.field.choice_cache: 884 yield choice 885 self.field.choice_cache = [] 886 memo = {} 887 for obj in self.queryset.all(): 888 if obj.pk not in memo: 889 memo[obj.pk] = 0 890 choice = self.choice(obj) 891 self.field_choice_cache.append(choice) 892 yield choice 893 else: 894 for choice in self.field.choice_cache: 895 yield choice 885 896 else: 897 memo = {} 886 898 for obj in self.queryset.all(): 887 yield self.choice(obj) 899 if obj.pk not in memo: 900 memo[obj.pk] = 0 901 yield self.choice(obj) 888 902 889 903 def __len__(self): 890 904 return len(self.queryset) … … 973 987 return None 974 988 try: 975 989 key = self.to_field_name or 'pk' 976 value = self.queryset.get(**{key: value}) 990 values = self.queryset.filter(**{key: value}) 991 # If you use limit_choices_to you could have more than one results 992 # for a single Instance. DISTINCT in the db won't work as expected 993 # so we do the check here. If SQL gets fixed remove this. 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.MultipleObjectReturned 977 1002 except (ValueError, self.queryset.model.DoesNotExist): 978 1003 raise ValidationError(self.error_messages['invalid_choice']) 979 1004 return value -
tests/regressiontests/model_fields/models.py
diff -r 06744e116e42 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 06744e116e42 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, Document12 from models import Foo, Bar, Baz, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document 12 13 13 14 # If PIL available, do these tests. 14 15 if Image: … … 104 105 # This should not crash. That counts as a win for our purposes. 105 106 Foo.objects.filter(d__gte=100000000000) 106 107 108 class BazForm(forms.ModelForm): 109 class Meta: 110 model = Baz 111 107 112 class ForeignKeyTests(test.TestCase): 108 113 def test_callable_default(self): 109 114 """Test the use of a lazy callable for ForeignKey.default""" … … 111 116 b = Bar.objects.create(b="bcd") 112 117 self.assertEqual(b.a, a) 113 118 119 def test_distinct_choice_limit(self): 120 """Doesn't make sense to offer the same ForeignKey multiple times in a form""" 121 a = Foo.objects.create(a='a', d=Decimal("-1")) 122 b = Foo.objects.create(a='b', d=Decimal("1")) 123 Bar.objects.create(b='ah', a=a) 124 Bar.objects.create(b='aha', a=a) 125 Bar.objects.create(b='bla', a=b) 126 form = BazForm() 127 fk_field = str(form['foo']) 128 self.assertEqual(len(re.findall(r'value="%s"' % b.pk, fk_field)), 0) 129 self.assertEqual(len(re.findall(r'value="%s"' % a.pk, fk_field)), 1) 130 131 def test_distinct_choice_limit_save(self): 132 """Doesn't make sense to offer the same ForeignKey multiple times in a form""" 133 a = Foo.objects.create(a='a', d=Decimal("-1")) 134 b = Foo.objects.create(a='b', d=Decimal("1")) 135 Bar.objects.create(b='ah', a=a) 136 Bar.objects.create(b='aha', a=a) 137 Bar.objects.create(b='bla', a=b) 138 form = BazForm({'foo': a.pk, 'a': 'a'}) 139 self.assertTrue(form.is_valid()) 140 obj = form.save() 141 self.assertEqual(obj.foo.pk, a.pk) 142 114 143 class DateTimeFieldTests(unittest.TestCase): 115 144 def test_datetimefield_to_python_usecs(self): 116 145 """DateTimeField.to_python should support usecs"""