RangeFilter

210 views
Skip to first unread message

Jay Vanderwood

unread,
Aug 24, 2020, 8:33:37 PM8/24/20
to django-filter
I'm using RangeFilter and I've dug around a bit and I can't quite determine how to validate the search ranges. I'd like to throw a form level error if they supply an out of range value similar to the standard form

def clean_field(self):
  if min_value < minimum:
    raise ValidationError(_('Value too low'))
  if max_value > maximum:
    raise ValidationError(_('Value too high'))  
etc.

1) I'm not sure if I can even do that from the filter, but as I've done other things to impact the html, I presume I can.
2) Even if I can, it is not clear from the documentation what the name of the two values are that I would like to inspect.

Am I just going about this wrong? 

Thanks for your time in advance,

-Jay

Carlton Gibson

unread,
Aug 25, 2020, 3:07:59 AM8/25/20
to django...@googlegroups.com
You’d have to do this when creating the form. 

If you pull the values off the model you can set validators on the fields. (Guessing ModelForm doesn’t do this for you as yet…)

Hopefully that’s enough to get you moving forwards. 
C. 

--
You received this message because you are subscribed to the Google Groups "django-filter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-filte...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-filter/be98c3f8-dad4-491a-8206-2d19bf6ddeadn%40googlegroups.com.

Jay Vanderwood

unread,
Aug 25, 2020, 4:45:54 PM8/25/20
to django-filter
Honestly, not really. I presume your intent was to point me at get_fields, but I guess I don't have a proper grasp of the abstract layers involved. Based on the examples I've followed, I have a filter, which effectively replaces the ModelForm:

views.py
  def RatingSearch(request):
    rating_list=Rating.objects.all()
    rating_filter=RatingFilter(request.GET, queryset=rating_list)
    return render (request, 'catalog/rating_search.html', { 'filter': rating_filter})

I've attempted to add some context values to this, but they are either not getting passed or the objects I assumed were in scope are not. I ended up changing my filter to so:

filters.py
  class RatingFilter(django_filters.FilterSet):
    rating_filter = django_filters.RangeFilter(field_name='rating', lookup_expr='range')
    class Meta:
      model = Rating
      fields = '__all__'

    @property
    def avg(self):
      qs=super(RatingFilter, self).qs
      return qs.filter(rating__gt=0).aggregate(Avg('rating'))

In my rating_search.html I was then able to access the average value of the ratings with a straight-forward {{ filter.avg.rating__avg }}. 

With that in mind, I presumed that any changes to the form would be done within the FilterSet. That being said, I can't sort out how to get to get_fields where I am.

-Jay

Carlton Gibson

unread,
Aug 26, 2020, 4:07:54 AM8/26/20
to django...@googlegroups.com
Hi.


On 25 Aug 2020, at 22:45, Jay Vanderwood <jvand...@gmail.com> wrote:

a proper grasp of the abstract layers involved. 

A FilterSet is just a group of Filters with a matching Form. 

A filter takes a value from the related form field and uses it to filter the QuerySet. 

The form is just a normal Django form. It’s generated for you, unless you take steps to override (the methods on FilterSet I linked you to.) 

Data validation is the job of the form. (This is the key point I think.)

So… 

All form fields take a `validators` kwarg. 

Filters take arbitrary kwargs, that are passed to the form field. 

At its most basic level then you can declare your filters passing the validators you want to apply to the field. 
If you need to further customise the form, look at the methods I linked you to previously. 

HTH. 

Kind Regards,

Carlton

Jay Vanderwood

unread,
Aug 26, 2020, 5:40:05 PM8/26/20
to django-filter
So, I'm not 100% sure if I went the direction you were pointing, but the sticking point for a bit there was that I had no idea what the name of the variable was to do a validation against. Ultimately I poked at it for a bit and came up with:

class RatingForm(forms.Form):
  def clean(self):
    cleaned_data = super(RatingForm, self).clean()
    search = cleaned_data['score_filter']
    if search[0] < 1:
      raise ValidationError(_('Score must be greater than 0.'))

But I'm getting the error: 'slice' object is not subscriptable.

Local vars
__class__ <class 'catalog.filters.RatingForm'>
cleaned_data {'score_filter': slice(Decimal('0'), Decimal('11'), None)}
search slice(Decimal('0'), Decimal('11'), None)

If I can't subscript it, I'm a little puzzled about how to access the minimum/maximum values.
Reply all
Reply to author
Forward
0 new messages