Index: django/contrib/admin/options.py =================================================================== --- django/contrib/admin/options.py (wersja 8502) +++ django/contrib/admin/options.py (kopia robocza) @@ -38,7 +38,7 @@ radio_fields = {} prepopulated_fields = {} - def formfield_for_dbfield(self, db_field, **kwargs): + def formfield_for_dbfield(self, db_field, request, **kwargs): """ Hook for specifying the form Field instance for a given database Field instance. @@ -106,26 +106,29 @@ # For ForeignKey or ManyToManyFields, use a special widget. if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): + if hasattr(self, 'dynamic_%s_choices' % db_field.name): + formfield = db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs) + else: + formfield = db_field.formfield(**kwargs) if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields: - kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) + formfield.widget = widgets.ForeignKeyRawIdWidget(db_field.rel) elif isinstance(db_field, models.ForeignKey) and db_field.name in self.radio_fields: - kwargs['widget'] = widgets.AdminRadioSelect(attrs={ + formfield.widget = widgets.AdminRadioSelect(attrs={ 'class': get_ul_class(self.radio_fields[db_field.name]), }) - kwargs['empty_label'] = db_field.blank and _('None') or None + formfield.empty_label = db_field.blank and _('None') or None else: if isinstance(db_field, models.ManyToManyField): # If it uses an intermediary model, don't show field in admin. if db_field.rel.through is not None: return None elif db_field.name in self.raw_id_fields: - kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel) - kwargs['help_text'] = '' + formfield.widget = widgets.ManyToManyRawIdWidget(db_field.rel) + formfield.help_text = '' elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): - kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) + formfield.widget = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) # Wrap the widget's render() method with a method that adds # extra HTML to the end of the rendered output. - formfield = db_field.formfield(**kwargs) # Don't wrap raw_id fields. Their add function is in the popup window. if not db_field.name in self.raw_id_fields: # formfield can be None if it came from a OneToOneField with @@ -134,6 +137,9 @@ formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site) return formfield + if isinstance(db_field, (models.OneToOneField)) and hasattr(self, 'dynamic_%s_choices' % db_field.name): + return db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs) + # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs) @@ -262,7 +268,7 @@ defaults = { "form": self.form, "fields": fields, - "formfield_callback": self.formfield_for_dbfield, + "formfield_callback": lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs), } defaults.update(kwargs) return modelform_factory(self.model, **defaults) @@ -770,7 +776,7 @@ "formset": self.formset, "fk_name": self.fk_name, "fields": fields, - "formfield_callback": self.formfield_for_dbfield, + "formfield_callback": lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs), "extra": self.extra, "max_num": self.max_num, }