Ticket #2445: choices_for_foo.diff
File choices_for_foo.diff, 5.8 KB (added by , 14 years ago) |
---|
-
docs/ref/models/fields.txt
999 999 DELETE`` constraint to the database field (perhaps using 1000 1000 :ref:`initial sql<initial-sql>`). 1001 1001 1002 .. versionadded:: 1.4 1003 1004 .. attribute:: Model.choices_for_FOO() 1005 1006 It is possible to limit choices with respect to ``self``. Creat a method called 1007 ``choices_for_FOO``, where ``FOO`` is the name of the field. The method needs 1008 to return a QuerySet:: 1009 1010 class MyModel(models.Model): 1011 user = models.ForeignKey(User) 1012 1013 def choices_for_user(self): 1014 # Make sure only active and currently associated users are in choices. 1015 return self.__class__.objects.exclude(is_active=False)| 1016 self.__class__.objects.filter(id=self.user) 1017 1002 1018 .. _ref-manytomany: 1003 1019 1004 1020 ``ManyToManyField`` -
django/db/models/base.py
353 353 else: 354 354 setattr(self, field.attname, val) 355 355 356 for field in self._meta.fields: 357 # Set the model field choices function on the field 358 # Refs #2445 359 if field.rel is None: 360 continue 361 choice_func = getattr(self, 'choices_for_%s' % field.name, None) 362 if callable(choice_func): 363 field.queryset = choice_func 364 356 365 if kwargs: 357 366 for prop in kwargs.keys(): 358 367 try: -
django/db/models/fields/__init__.py
362 362 first_choice = include_blank and blank_choice or [] 363 363 if self.choices: 364 364 return first_choice + list(self.choices) 365 rel_model = self.rel.to366 365 if hasattr(self.rel, 'get_related_field'): 367 lst = [(getattr(x, self.rel.get_related_field().attname), smart_unicode(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]366 lst = [(getattr(x, self.rel.get_related_field().attname), smart_unicode(x)) for x in self.queryset] 368 367 else: 369 lst = [(x._get_pk_val(), smart_unicode(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]368 lst = [(x._get_pk_val(), smart_unicode(x)) for x in self.queryset] 370 369 return first_choice + lst 371 370 372 371 def get_choices_default(self): … … 447 446 "Returns the value of this field in the given model instance." 448 447 return getattr(obj, self.attname) 449 448 449 def _get_queryset(self): 450 if hasattr(self, '_queryset'): 451 return self._queryset() 452 return self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to) 453 454 def _set_queryset(self, qs): 455 self._queryset = qs 456 457 queryset = property(_get_queryset, _set_queryset) 458 450 459 class AutoField(Field): 451 460 description = _("Integer") 452 461 -
django/db/models/fields/related.py
847 847 return 848 848 849 849 using = router.db_for_read(model_instance.__class__, instance=model_instance) 850 qs = self.rel.to._default_manager.using(using).filter( 851 **{self.rel.field_name: value} 852 ) 853 qs = qs.complex_filter(self.rel.limit_choices_to) 850 qs = self.queryset.using(using).filter(**{self.rel.field_name: value}) 854 851 if not qs.exists(): 855 852 raise exceptions.ValidationError(self.error_messages['invalid'] % { 856 853 'model': self.rel.to._meta.verbose_name, 'pk': value}) … … 910 907 db = kwargs.pop('using', None) 911 908 defaults = { 912 909 'form_class': forms.ModelChoiceField, 913 'queryset': self. rel.to._default_manager.using(db).complex_filter(self.rel.limit_choices_to),910 'queryset': self.queryset.using(db), 914 911 'to_field_name': self.rel.field_name, 915 912 } 916 913 defaults.update(kwargs) -
tests/modeltests/choices/tests.py
1 from django.db.models.query import QuerySet 1 2 from django.test import TestCase 2 3 3 4 from models import Person … … 21 22 a.gender = 'U' 22 23 self.assertEqual(a.get_gender_display(), 'U') 23 24 25 def test_callable(self): 26 for name, gender, parent in (('Adrian', 'M', None), ('Simon', 'M', 1), ('Karen', 'F', 1), ('Brian', 'F', 2)): 27 p = Person.objects.create(name=name, gender=gender, parent_id=parent) 28 29 parent = p._meta.get_field('parent') 30 self.assertIsInstance(parent.queryset, QuerySet) 31 self.assertNotIn(p, parent.queryset) -
tests/modeltests/choices/models.py
19 19 class Person(models.Model): 20 20 name = models.CharField(max_length=20) 21 21 gender = models.CharField(max_length=1, choices=GENDER_CHOICES) 22 parent = models.ForeignKey('self', blank=True, null=True, related_name='child') 22 23 23 24 def __unicode__(self): 24 25 return self.name 26 27 def choices_for_parent(self): 28 return self.__class__.objects.exclude(id=self.id)