How to filter price range for products in django?

Question:

I am trying to filter my products list by price specified by user(min and max price).I have two input box for taking price range.’price’ is one of the column in my database table.I am getting error as int() argument must be a string or a number, not ‘dict’.I have include my template file and small part of views file.

Models.py,

class Add_prod(models.Model):
    book = models.CharField("Book Name",max_length=40)
    author = models.CharField("Author",max_length=30)
    price = models.PositiveIntegerField("Price")
    image = models.ImageField(upload_to='images',null=True)
    cat = models.ForeignKey(Add_cat,on_delete=models.PROTECT)

    def __unicode__(self):
        return "%s" % (self.cat)

My template file,

<p>Price</p>
<input type="text" name="min_price" maxlength="4" size="3" >
to <input type="text" name="max_price" maxlength="4" size="3"> 
<input type="submit" value="Go">

views.py,

@csrf_protect  
def welcome_user(request): 
    if 'min_price' in request.GET:
        filter_price1 = request.GET.get('min_price')
        filter_price2 = request.GET.get('max_price')
        if filter_price1 =='':
            filter_price1=0
        if filter_price2=='':
            filter_price2=Add_prod.objects.all().aggregate(Max('price'))
        my_products = Add_prod.objects.filter(price__range=(filter_price1,filter_price2))
        context = { "products":my_products}
   return render(request,"welcome-user.html",context)

I also tried like this,

my_products = Add_prod.objects.raw('SELECT * FROM books_add_prod where price between filter_price1 and filter_price2')
Asked By: Kiran

||

Answers:

Maybe this line wrong filter_price2=Add_prod.objects.all().aggregate(Max('price'))
Cause aggragate will return a dict

See this docs Aggragation

Try this:
my_products=Add_prod.objects.filter(price__range(filter_price1,filter_price2['price_max']))

Answered By: 張泰瑋

Use aggregation (cheatsheet) as follows to determine the maximum price:

from decimal import Decimal as D
...
price1 = D(request.GET.get('min_price', 0)) 
price2 = D(request.GET.get('max_price', 0))

if not price2:
    price2 = Add_prod.objects.aggregate(Max('price'))['price__max']

my_products = Add_prod.objects.filter(price__range=(price1, price2))

On a different note, why do you use text inputs for price which I assume is a DecimalField? What about a number input (or a django form) in order to make sure that the casts in your view don’t raise errors :

<input type="number" name="min_price" min="0" step="0.01" >
Answered By: user2390182

Here is what worked for me, this might not be the optimal way to do it. But it works so anyone from future could give it a try:

   <form method="get">
    <input type="text" name="min_price" maxlength="4" size="3" required>         
    to <input type="text" name="max_price" maxlength="4" size="3" required> 
    <input type="submit" value="Go">
    </form>

And In your Views:

if 'min_price' in request.GET:    
        filter_price1 = request.GET.get('min_price')
        filter_price2 = request.GET.get('max_price')
        if filter_price1 =='':
            filter_price1=0
        products = Products.objects.filter(price__range=(filter_price1,filter_price2))
Answered By: Atit Bimali
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.