Ticket #3987: dynamic_related_3987.2.diff

File dynamic_related_3987.2.diff, 4.6 KB (added by mikeblake, 7 years ago)

Updated to revision 8151

  • django/contrib/admin/options.py

     
    122122    radio_fields = {}
    123123    prepopulated_fields = {}
    124124
    125     def formfield_for_dbfield(self, db_field, **kwargs):
     125    def formfield_for_dbfield(self, db_field, request, **kwargs):
    126126        """
    127127        Hook for specifying the form Field instance for a given database Field
    128128        instance.
     
    152152
    153153        # For ForeignKey or ManyToManyFields, use a special widget.
    154154        if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
     155            if hasattr(self, 'dynamic_%s_choices' % db_field.name):
     156                formfield = db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs)
     157            else:
     158                formfield = db_field.formfield(**kwargs)
    155159            if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
    156                 kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
     160                formfield.widget = widgets.ForeignKeyRawIdWidget(db_field.rel)
    157161            elif isinstance(db_field, models.ForeignKey) and db_field.name in self.radio_fields:
    158                 kwargs['widget'] = widgets.AdminRadioSelect(attrs={
     162                formfield.widget = widgets.AdminRadioSelect(attrs={
    159163                    'class': get_ul_class(self.radio_fields[db_field.name]),
    160164                })
    161                 kwargs['empty_label'] = db_field.blank and _('None') or None
     165                formfield.empty_label = db_field.blank and _('None') or None
    162166            else:
    163167                if isinstance(db_field, models.ManyToManyField):
    164168                    # If it uses an intermediary model, don't show field in admin.
    165169                    if db_field.rel.through is not None:
    166170                        return None
    167171                    elif db_field.name in self.raw_id_fields:
    168                         kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel)
    169                         kwargs['help_text'] = ''
     172                        formfield.widget = widgets.ManyToManyRawIdWidget(db_field.rel)
     173                        formfield.help_text = ''
    170174                    elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
    171                         kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
     175                        formfield.widget = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
    172176            # Wrap the widget's render() method with a method that adds
    173177            # extra HTML to the end of the rendered output.
    174             formfield = db_field.formfield(**kwargs)
    175178            # Don't wrap raw_id fields. Their add function is in the popup window.
    176179            if not db_field.name in self.raw_id_fields:
    177180                formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site)
    178181            return formfield
    179        
     182 
     183        if isinstance(db_field, (models.OneToOneField)) and hasattr(self, 'dynamic_%s_choices' % db_field.name):
     184            return db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs)
     185           
    180186        if db_field.choices and db_field.name in self.radio_fields:
    181187            kwargs['widget'] = widgets.AdminRadioSelect(
    182188                choices=db_field.get_choices(include_blank=db_field.blank,
     
    322328            fields = flatten_fieldsets(self.declared_fieldsets)
    323329        else:
    324330            fields = None
    325         return modelform_factory(self.model, form=self.form, fields=fields, formfield_callback=self.formfield_for_dbfield)
     331        return modelform_factory(self.model, form=self.form, fields=fields, formfield_callback=lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs))
    326332
    327333    def get_formsets(self, request, obj=None):
    328334        for inline in self.inline_instances:
     
    728734            fields = None
    729735        return inlineformset_factory(self.parent_model, self.model,
    730736            form=self.form, formset=self.formset, fk_name=self.fk_name,
    731             fields=fields, formfield_callback=self.formfield_for_dbfield,
     737            fields=fields, formfield_callback=lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs),
    732738            extra=self.extra, max_num=self.max_num)
    733739
    734740    def get_fieldsets(self, request, obj=None):
Back to Top