Code

Ticket #3987: dynamic_related_3987.2.diff

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

Updated to revision 8151

Line 
1Index: django/contrib/admin/options.py
2===================================================================
3--- django/contrib/admin/options.py     (revision 8151)
4+++ django/contrib/admin/options.py     (working copy)
5@@ -122,7 +122,7 @@
6     radio_fields = {}
7     prepopulated_fields = {}
8 
9-    def formfield_for_dbfield(self, db_field, **kwargs):
10+    def formfield_for_dbfield(self, db_field, request, **kwargs):
11         """
12         Hook for specifying the form Field instance for a given database Field
13         instance.
14@@ -152,31 +152,37 @@
15 
16         # For ForeignKey or ManyToManyFields, use a special widget.
17         if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
18+            if hasattr(self, 'dynamic_%s_choices' % db_field.name):
19+                formfield = db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs)
20+            else:
21+                formfield = db_field.formfield(**kwargs)
22             if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
23-                kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
24+                formfield.widget = widgets.ForeignKeyRawIdWidget(db_field.rel)
25             elif isinstance(db_field, models.ForeignKey) and db_field.name in self.radio_fields:
26-                kwargs['widget'] = widgets.AdminRadioSelect(attrs={
27+                formfield.widget = widgets.AdminRadioSelect(attrs={
28                     'class': get_ul_class(self.radio_fields[db_field.name]),
29                 })
30-                kwargs['empty_label'] = db_field.blank and _('None') or None
31+                formfield.empty_label = db_field.blank and _('None') or None
32             else:
33                 if isinstance(db_field, models.ManyToManyField):
34                     # If it uses an intermediary model, don't show field in admin.
35                     if db_field.rel.through is not None:
36                         return None
37                     elif db_field.name in self.raw_id_fields:
38-                        kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel)
39-                        kwargs['help_text'] = ''
40+                        formfield.widget = widgets.ManyToManyRawIdWidget(db_field.rel)
41+                        formfield.help_text = ''
42                     elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
43-                        kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
44+                        formfield.widget = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
45             # Wrap the widget's render() method with a method that adds
46             # extra HTML to the end of the rendered output.
47-            formfield = db_field.formfield(**kwargs)
48             # Don't wrap raw_id fields. Their add function is in the popup window.
49             if not db_field.name in self.raw_id_fields:
50                 formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site)
51             return formfield
52-       
53+
54+        if isinstance(db_field, (models.OneToOneField)) and hasattr(self, 'dynamic_%s_choices' % db_field.name):
55+            return db_field.formfield(queryset = getattr(self, 'dynamic_%s_choices' % db_field.name)(request, db_field.rel.to), **kwargs)
56+           
57         if db_field.choices and db_field.name in self.radio_fields:
58             kwargs['widget'] = widgets.AdminRadioSelect(
59                 choices=db_field.get_choices(include_blank=db_field.blank,
60@@ -322,7 +328,7 @@
61             fields = flatten_fieldsets(self.declared_fieldsets)
62         else:
63             fields = None
64-        return modelform_factory(self.model, form=self.form, fields=fields, formfield_callback=self.formfield_for_dbfield)
65+        return modelform_factory(self.model, form=self.form, fields=fields, formfield_callback=lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs))
66 
67     def get_formsets(self, request, obj=None):
68         for inline in self.inline_instances:
69@@ -728,7 +734,7 @@
70             fields = None
71         return inlineformset_factory(self.parent_model, self.model,
72             form=self.form, formset=self.formset, fk_name=self.fk_name,
73-            fields=fields, formfield_callback=self.formfield_for_dbfield,
74+            fields=fields, formfield_callback=lambda f, **kwargs: self.formfield_for_dbfield(f, request, **kwargs),
75             extra=self.extra, max_num=self.max_num)
76 
77     def get_fieldsets(self, request, obj=None):