Code

Ticket #3987: customfilters.diff

File customfilters.diff, 7.8 KB (added by Baptiste <baptiste.goupil@…>, 7 years ago)

the patch

Line 
1Index: db/models/fields/related.py
2===================================================================
3--- db/models/fields/related.py (révision 4970)
4+++ db/models/fields/related.py (copie de travail)
5@@ -545,7 +545,9 @@
6         setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
7 
8     def formfield(self, **kwargs):
9-        defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
10+        filter_field = kwargs.get('filter', {})
11+        if kwargs.has_key('filter'): del kwargs['filter']
12+        defaults = {'queryset': self.rel.to._default_manager.all().filter(**filter_field), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
13         defaults.update(kwargs)
14         return forms.ModelChoiceField(**defaults)
15 
16@@ -606,7 +608,9 @@
17             cls._meta.one_to_one_field = self
18 
19     def formfield(self, **kwargs):
20-        defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
21+        filter_field = kwargs.get('filter', {})
22+        if kwargs.has_key('filter'): del kwargs['filter']
23+        defaults = {'queryset': self.rel.to._default_manager.all().filter(**filter_field), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
24         defaults.update(kwargs)
25         return forms.ModelChoiceField(**defaults)
26 
27@@ -714,9 +718,11 @@
28     def formfield(self, **kwargs):
29         # If initial is passed in, it's a list of related objects, but the
30         # MultipleChoiceField takes a list of IDs.
31+        filter_field = kwargs.get('filter', {})
32+        if kwargs.has_key('filter'): del kwargs['filter']
33         if kwargs.get('initial') is not None:
34             kwargs['initial'] = [i._get_pk_val() for i in kwargs['initial']]
35-        defaults = {'queryset' : self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
36+        defaults = {'queryset' : self.rel.to._default_manager.all().filter(**filter_field), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
37         defaults.update(kwargs)
38         return forms.ModelMultipleChoiceField(**defaults)
39 
40Index: contrib/admin/options.py
41===================================================================
42--- contrib/admin/options.py    (révision 4970)
43+++ contrib/admin/options.py    (copie de travail)
44@@ -208,10 +208,12 @@
45 
46         If kwargs are given, they're passed to the form Field's constructor.
47         """
48+        filter_field = kwargs.get('filter_field', {})
49+        if kwargs.has_key('filter_field'): del kwargs['filter_field']
50         # For ManyToManyFields with a filter interface, use a special Widget.
51         if isinstance(db_field, models.ManyToManyField) and db_field.name in (self.filter_vertical + self.filter_horizontal):
52             kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
53-            return db_field.formfield(**kwargs)
54+            return db_field.formfield(filter=filter_field, **kwargs)
55 
56         # For DateTimeFields, use a special field and widget.
57         if isinstance(db_field, models.DateTimeField):
58@@ -233,11 +235,11 @@
59         if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
60             if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
61                 kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
62-                return db_field.formfield(**kwargs)
63+                return db_field.formfield(filter=filter_field, **kwargs)
64             else:
65                 # Wrap the widget's render() method with a method that adds
66                 # extra HTML to the end of the rendered output.
67-                formfield = db_field.formfield(**kwargs)
68+                formfield = db_field.formfield(filter=filter_field, **kwargs)
69                 formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel)
70                 return formfield
71 
72@@ -375,7 +377,7 @@
73             request.user.message_set.create(message=msg)
74             return HttpResponseRedirect("../")
75 
76-    def add_view(self, request, form_url=''):
77+    def add_view(self, request, form_url='', fields_filters={}):
78         "The 'add' admin view for this model."
79         from django.contrib.admin.views.main import render_change_form
80         model = self.model
81@@ -392,7 +394,7 @@
82             # Object list will give 'Permission Denied', so go back to admin home
83             post_url = '../../../'
84 
85-        ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield)
86+        ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield, fields_filters=fields_filters)
87 
88         if request.POST:
89             new_data = request.POST.copy()
90@@ -413,7 +415,7 @@
91         })
92         return render_change_form(self, model, model.AddManipulator(), c, add=True)
93 
94-    def change_view(self, request, object_id):
95+    def change_view(self, request, object_id, fields_filters={}):
96         "The 'change' admin view for this model."
97         from django.contrib.admin.views.main import render_change_form
98         model = self.model
99@@ -437,7 +439,7 @@
100         if request.POST and request.POST.has_key("_saveasnew"):
101             return self.add_view(request, form_url='../../add/')
102 
103-        ModelForm = forms.form_for_instance(obj, formfield_callback=self.formfield_for_dbfield)
104+        ModelForm = forms.form_for_instance(obj, formfield_callback=self.formfield_for_dbfield, fields_filters=fields_filters)
105 
106         if request.POST:
107             new_data = request.POST.copy()
108Index: newforms/models.py
109===================================================================
110--- newforms/models.py  (révision 4970)
111+++ newforms/models.py  (copie de travail)
112@@ -56,7 +56,7 @@
113         return save_instance(self, instance, commit)
114     return save
115 
116-def form_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield()):
117+def form_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield(), fields_filters={}):
118     """
119     Returns a Form class for the given Django model class.
120 
121@@ -71,13 +71,17 @@
122     for f in opts.fields + opts.many_to_many:
123         if not f.editable:
124             continue
125-        formfield = formfield_callback(f)
126+        filter_field = fields_filters.get(f.name)
127+        if filter_field:
128+            formfield = formfield_callback(f, filter_field=filter_field)
129+        else:
130+            formfield = formfield_callback(f)
131         if formfield:
132             field_list.append((f.name, formfield))
133     fields = SortedDictFromList(field_list)
134     return type(opts.object_name + 'Form', (form,), {'base_fields': fields, '_model': model, 'save': model_save})
135 
136-def form_for_instance(instance, form=BaseForm, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
137+def form_for_instance(instance, form=BaseForm, fields_filters={}, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
138     """
139     Returns a Form class for the given Django model instance.
140 
141@@ -95,7 +99,11 @@
142         if not f.editable:
143             continue
144         current_value = f.value_from_object(instance)
145-        formfield = formfield_callback(f, initial=current_value)
146+        filter_field = fields_filters.get(f.name)
147+        if filter_field:
148+            formfield = formfield_callback(f, filter_field=filter_field, initial=current_value)
149+        else:
150+            formfield = formfield_callback(f, initial=current_value)
151         if formfield:
152             field_list.append((f.name, formfield))
153     fields = SortedDictFromList(field_list)