Ticket #3987: customfilters.diff

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

the patch

  • db/models/fields/related.py

     
    545545        setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
    546546
    547547    def formfield(self, **kwargs):
    548         defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
     548        filter_field = kwargs.get('filter', {})
     549        if kwargs.has_key('filter'): del kwargs['filter']
     550        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}
    549551        defaults.update(kwargs)
    550552        return forms.ModelChoiceField(**defaults)
    551553
     
    606608            cls._meta.one_to_one_field = self
    607609
    608610    def formfield(self, **kwargs):
    609         defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
     611        filter_field = kwargs.get('filter', {})
     612        if kwargs.has_key('filter'): del kwargs['filter']
     613        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}
    610614        defaults.update(kwargs)
    611615        return forms.ModelChoiceField(**defaults)
    612616
     
    714718    def formfield(self, **kwargs):
    715719        # If initial is passed in, it's a list of related objects, but the
    716720        # MultipleChoiceField takes a list of IDs.
     721        filter_field = kwargs.get('filter', {})
     722        if kwargs.has_key('filter'): del kwargs['filter']
    717723        if kwargs.get('initial') is not None:
    718724            kwargs['initial'] = [i._get_pk_val() for i in kwargs['initial']]
    719         defaults = {'queryset' : self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
     725        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}
    720726        defaults.update(kwargs)
    721727        return forms.ModelMultipleChoiceField(**defaults)
    722728
  • contrib/admin/options.py

     
    208208
    209209        If kwargs are given, they're passed to the form Field's constructor.
    210210        """
     211        filter_field = kwargs.get('filter_field', {})
     212        if kwargs.has_key('filter_field'): del kwargs['filter_field']
    211213        # For ManyToManyFields with a filter interface, use a special Widget.
    212214        if isinstance(db_field, models.ManyToManyField) and db_field.name in (self.filter_vertical + self.filter_horizontal):
    213215            kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
    214             return db_field.formfield(**kwargs)
     216            return db_field.formfield(filter=filter_field, **kwargs)
    215217
    216218        # For DateTimeFields, use a special field and widget.
    217219        if isinstance(db_field, models.DateTimeField):
     
    233235        if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
    234236            if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
    235237                kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
    236                 return db_field.formfield(**kwargs)
     238                return db_field.formfield(filter=filter_field, **kwargs)
    237239            else:
    238240                # Wrap the widget's render() method with a method that adds
    239241                # extra HTML to the end of the rendered output.
    240                 formfield = db_field.formfield(**kwargs)
     242                formfield = db_field.formfield(filter=filter_field, **kwargs)
    241243                formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel)
    242244                return formfield
    243245
     
    375377            request.user.message_set.create(message=msg)
    376378            return HttpResponseRedirect("../")
    377379
    378     def add_view(self, request, form_url=''):
     380    def add_view(self, request, form_url='', fields_filters={}):
    379381        "The 'add' admin view for this model."
    380382        from django.contrib.admin.views.main import render_change_form
    381383        model = self.model
     
    392394            # Object list will give 'Permission Denied', so go back to admin home
    393395            post_url = '../../../'
    394396
    395         ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield)
     397        ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield, fields_filters=fields_filters)
    396398
    397399        if request.POST:
    398400            new_data = request.POST.copy()
     
    413415        })
    414416        return render_change_form(self, model, model.AddManipulator(), c, add=True)
    415417
    416     def change_view(self, request, object_id):
     418    def change_view(self, request, object_id, fields_filters={}):
    417419        "The 'change' admin view for this model."
    418420        from django.contrib.admin.views.main import render_change_form
    419421        model = self.model
     
    437439        if request.POST and request.POST.has_key("_saveasnew"):
    438440            return self.add_view(request, form_url='../../add/')
    439441
    440         ModelForm = forms.form_for_instance(obj, formfield_callback=self.formfield_for_dbfield)
     442        ModelForm = forms.form_for_instance(obj, formfield_callback=self.formfield_for_dbfield, fields_filters=fields_filters)
    441443
    442444        if request.POST:
    443445            new_data = request.POST.copy()
  • newforms/models.py

     
    5656        return save_instance(self, instance, commit)
    5757    return save
    5858
    59 def form_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield()):
     59def form_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield(), fields_filters={}):
    6060    """
    6161    Returns a Form class for the given Django model class.
    6262
     
    7171    for f in opts.fields + opts.many_to_many:
    7272        if not f.editable:
    7373            continue
    74         formfield = formfield_callback(f)
     74        filter_field = fields_filters.get(f.name)
     75        if filter_field:
     76            formfield = formfield_callback(f, filter_field=filter_field)
     77        else:
     78            formfield = formfield_callback(f)
    7579        if formfield:
    7680            field_list.append((f.name, formfield))
    7781    fields = SortedDictFromList(field_list)
    7882    return type(opts.object_name + 'Form', (form,), {'base_fields': fields, '_model': model, 'save': model_save})
    7983
    80 def form_for_instance(instance, form=BaseForm, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
     84def form_for_instance(instance, form=BaseForm, fields_filters={}, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
    8185    """
    8286    Returns a Form class for the given Django model instance.
    8387
     
    9599        if not f.editable:
    96100            continue
    97101        current_value = f.value_from_object(instance)
    98         formfield = formfield_callback(f, initial=current_value)
     102        filter_field = fields_filters.get(f.name)
     103        if filter_field:
     104            formfield = formfield_callback(f, filter_field=filter_field, initial=current_value)
     105        else:
     106            formfield = formfield_callback(f, initial=current_value)
    99107        if formfield:
    100108            field_list.append((f.name, formfield))
    101109    fields = SortedDictFromList(field_list)
Back to Top