Ticket #3987: dynamic_choice_9014.diff

File dynamic_choice_9014.diff, 4.4 KB (added by mwdiers, 7 years ago)

Updated patch to rev 9014. This will work with 1.0 also.

  • django/contrib/admin/options.py

     
    3939    radio_fields = {}
    4040    prepopulated_fields = {}
    4141
    42     def formfield_for_dbfield(self, db_field, **kwargs):
     42    def formfield_for_dbfield(self, db_field, request, **kwargs):
    4343        """
    4444        Hook for specifying the form Field instance for a given database Field
    4545        instance.
     
    112112
    113113        # For ForeignKey or ManyToManyFields, use a special widget.
    114114        if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
     115            if hasattr(self, 'dynamic_%s_choices' % db_field.name):
     116                formfield = db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs)
     117            else:
     118                formfield = db_field.formfield(**kwargs)
    115119            if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
    116                 kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
     120                formfield.widget = widgets.ForeignKeyRawIdWidget(db_field.rel)
    117121            elif isinstance(db_field, models.ForeignKey) and db_field.name in self.radio_fields:
    118                 kwargs['widget'] = widgets.AdminRadioSelect(attrs={
     122                formfield.widget = widgets.AdminRadioSelect(attrs={
    119123                    'class': get_ul_class(self.radio_fields[db_field.name]),
    120124                })
    121                 kwargs['empty_label'] = db_field.blank and _('None') or None
     125                formfield.empty_label = db_field.blank and _('None') or None
    122126            else:
    123127                if isinstance(db_field, models.ManyToManyField):
    124128                    # If it uses an intermediary model, don't show field in admin.
    125129                    if db_field.rel.through is not None:
    126130                        return None
    127131                    elif db_field.name in self.raw_id_fields:
    128                         kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel)
    129                         kwargs['help_text'] = ''
     132                        formfield.widget = widgets.ManyToManyRawIdWidget(db_field.rel)
     133                        formfield.help_text = ''
    130134                    elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
    131                         kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
     135                        formfield.widget = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
    132136            # Wrap the widget's render() method with a method that adds
    133137            # extra HTML to the end of the rendered output.
    134             formfield = db_field.formfield(**kwargs)
    135138            # Don't wrap raw_id fields. Their add function is in the popup window.
    136139            if not db_field.name in self.raw_id_fields:
    137140                # formfield can be None if it came from a OneToOneField with
     
    140143                    formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site)
    141144            return formfield
    142145
     146        if isinstance(db_field, (models.OneToOneField)) and hasattr(self, 'dynamic_%s_choices' % db_field.name):
     147            return db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs)
     148           
    143149        # For any other type of field, just call its formfield() method.
    144150        return db_field.formfield(**kwargs)
    145151
     
    271277            "form": self.form,
    272278            "fields": fields,
    273279            "exclude": exclude + kwargs.get("exclude", []),
    274             "formfield_callback": self.formfield_for_dbfield,
     280            "formfield_callback": lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs),
    275281        }
    276282        defaults.update(kwargs)
    277283        return modelform_factory(self.model, **defaults)
     
    787793            "fk_name": self.fk_name,
    788794            "fields": fields,
    789795            "exclude": exclude + kwargs.get("exclude", []),
    790             "formfield_callback": self.formfield_for_dbfield,
     796            "formfield_callback": lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs),
    791797            "extra": self.extra,
    792798            "max_num": self.max_num,
    793799        }
Back to Top