Ticket #8648: 8648.diff

File 8648.diff, 4.9 KB (added by SmileyChris, 7 years ago)
  • django/db/models/fields/related.py

     
    686686        setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
    687687       
    688688    def formfield(self, **kwargs):
    689         defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to)}
     689        defaults = {
     690            'form_class': forms.ModelChoiceField,
     691            'queryset': self.rel.to._default_manager.complex_filter(
     692                                                    self.rel.limit_choices_to),
     693            'to_field_name': self.rel.field_name,
     694        }
    690695        defaults.update(kwargs)
    691696        return super(ForeignKey, self).formfield(**defaults)
    692697
  • django/forms/models.py

     
    460460        if self.field.cache_choices:
    461461            if self.field.choice_cache is None:
    462462                self.field.choice_cache = [
    463                     (obj.pk, self.field.label_from_instance(obj))
    464                     for obj in self.queryset.all()
     463                    self.choice(obj) for obj in self.queryset.all()
    465464                ]
    466465            for choice in self.field.choice_cache:
    467466                yield choice
    468467        else:
    469468            for obj in self.queryset.all():
    470                 yield (obj.pk, self.field.label_from_instance(obj))
     469                yield self.choice(obj)
    471470
     471    def choice(self, obj):
     472        if self.field.to_field_name:
     473            key = getattr(obj, self.field.to_field_name)
     474        else:
     475            key = obj.pk
     476        return (key, self.field.label_from_instance(obj))
     477
     478
    472479class ModelChoiceField(ChoiceField):
    473480    """A ChoiceField whose choices are a model QuerySet."""
    474481    # This class is a subclass of ChoiceField for purity, but it doesn't
     
    480487
    481488    def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
    482489                 required=True, widget=None, label=None, initial=None,
    483                  help_text=None, *args, **kwargs):
     490                 help_text=None, to_field_name=None, *args, **kwargs):
    484491        self.empty_label = empty_label
    485492        self.cache_choices = cache_choices
    486493
     
    490497                       *args, **kwargs)
    491498        self.queryset = queryset
    492499        self.choice_cache = None
     500        self.to_field_name = to_field_name
    493501
    494502    def _get_queryset(self):
    495503        return self._queryset
     
    532540        if value in EMPTY_VALUES:
    533541            return None
    534542        try:
    535             value = self.queryset.get(pk=value)
     543            key = self.to_field_name or 'pk'
     544            value = self.queryset.get(**{key: value})
    536545        except self.queryset.model.DoesNotExist:
    537546            raise ValidationError(self.error_messages['invalid_choice'])
    538547        return value
  • tests/modeltests/model_forms/models.py

     
    120120class ArticleStatus(models.Model):
    121121    status = models.CharField(max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True)
    122122
     123class Inventory(models.Model):
     124   barcode = models.PositiveIntegerField(unique=True)
     125   parent = models.ForeignKey('self', to_field='barcode', blank=True, null=True)
     126   name = models.CharField(blank=False, max_length=20)
     127
     128   def __unicode__(self):
     129      return self.name
     130
    123131__test__ = {'API_TESTS': """
    124132>>> from django import forms
    125133>>> from django.forms.models import ModelForm, model_to_dict
     
    11521160...
    11531161ValidationError: [u'Select a valid choice. z is not one of the available choices.']
    11541162
     1163# Foreign keys which use to_field #############################################
     1164
     1165>>> apple = Inventory.objects.create(barcode=86, name='Apple')
     1166>>> pear = Inventory.objects.create(barcode=22, name='Pear')
     1167>>> core = Inventory.objects.create(barcode=87, name='Core', parent=apple)
     1168
     1169>>> field = ModelChoiceField(Inventory.objects.all(), to_field_name='barcode')
     1170>>> for choice in field.choices:
     1171...     print choice
     1172(u'', u'---------')
     1173(86, u'Apple')
     1174(22, u'Pear')
     1175(87, u'Core')
     1176
     1177>>> class InventoryForm(ModelForm):
     1178...     class Meta:
     1179...         model = Inventory
     1180>>> form = InventoryForm(instance=core)
     1181>>> print form['parent']
     1182<select name="parent" id="id_parent">
     1183<option value="">---------</option>
     1184<option value="86" selected="selected">Apple</option>
     1185<option value="22">Pear</option>
     1186<option value="87">Core</option>
     1187</select>
     1188
     1189>>> data = model_to_dict(core)
     1190>>> data['parent'] = '22'
     1191>>> form = InventoryForm(data=data, instance=core)
     1192>>> core = form.save()
     1193>>> core.parent
     1194<Inventory: Pear>
    11551195"""}
Back to Top