Django

Code

Ticket #8648: 8648.2.diff

File 8648.2.diff, 7.5 kB (added by SmileyChris, 4 months ago)
  • django/db/models/fields/related.py

    old new  
    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

    old new  
    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

    old new  
    7878class WriterProfile(models.Model): 
    7979    writer = models.OneToOneField(Writer, primary_key=True) 
    8080    age = models.PositiveIntegerField() 
    81      
     81 
    8282    def __unicode__(self): 
    8383        return "%s is %s" % (self.writer, self.age) 
    8484 
     
    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 
     
    11171125Traceback (most recent call last): 
    11181126... 
    11191127ValidationError: [u'Enter only digits separated by commas.'] 
    1120 >>> f.clean(',,,,')  
     1128>>> f.clean(',,,,') 
    11211129u',,,,' 
    11221130>>> f.clean('1.2') 
    11231131Traceback (most recent call last): 
     
    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"""} 
  • tests/regressiontests/admin_widgets/models.py

    old new  
    55 
    66class Member(models.Model): 
    77    name = models.CharField(max_length=100) 
    8      
     8 
    99    def __unicode__(self): 
    1010        return self.name 
    1111 
    1212class Band(models.Model): 
    1313    name = models.CharField(max_length=100) 
    1414    members = models.ManyToManyField(Member) 
    15      
     15 
    1616    def __unicode__(self): 
    1717        return self.name 
    1818 
     
    2020    band = models.ForeignKey(Band) 
    2121    name = models.CharField(max_length=100) 
    2222    cover_art = models.FileField(upload_to='albums') 
    23      
     23 
    2424    def __unicode__(self): 
    2525        return self.name 
    2626 
     27class Inventory(models.Model): 
     28   barcode = models.PositiveIntegerField(unique=True) 
     29   parent = models.ForeignKey('self', to_field='barcode', blank=True, null=True) 
     30   name = models.CharField(blank=False, max_length=20) 
     31 
     32   def __unicode__(self): 
     33      return self.name 
     34 
    2735__test__ = {'WIDGETS_TESTS': """ 
    2836>>> from datetime import datetime 
    2937>>> from django.utils.html import escape, conditional_escape 
     
    8492>>> w._has_changed([1, 2], [u'1', u'3']) 
    8593True 
    8694 
     95# Check that ForeignKeyRawIdWidget works with fields which aren't related to 
     96# the model's primary key. 
     97>>> apple = Inventory.objects.create(barcode=86, name='Apple') 
     98>>> pear = Inventory.objects.create(barcode=22, name='Pear') 
     99>>> core = Inventory.objects.create(barcode=87, name='Core', parent=apple) 
     100>>> rel = Inventory._meta.get_field('parent').rel 
     101>>> w = ForeignKeyRawIdWidget(rel) 
     102>>> print w.render('test', core.parent_id, attrs={}) 
     103<input type="text" name="test" value="86" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/inventory/" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="/admin_media/img/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a>&nbsp;<strong>Apple</strong> 
    87104""" % { 
    88105    'ADMIN_MEDIA_PREFIX': settings.ADMIN_MEDIA_PREFIX, 
    89106    'STORAGE_URL': default_storage.url(''),