Home > other >  Django, Python: Can't filter products with passing values true the get request and order the pr
Django, Python: Can't filter products with passing values true the get request and order the pr

Time:12-08

I'm trying to filter some products and order the filtered products by price ascending and descending.

This is my code in the view:

def is_valid_queryparam(param):
    return param != '' and param is not None

def filter(request):
  if request.GET:
      price_min = request.GET.get('priceMin')
      price_max = request.GET.get('priceMax')
      sort_by = request.GET.get("sort", "l2h")

      if is_valid_queryparam(price_min):
          if sort_by == "l2h":
              products = Product.objects.filter(price__gte=price_min).order_by('price')
          elif sort_by == "h2l":
              products = Product.objects.filter(price__gte=price_min).order_by('-price')
          paginator = Paginator(products, 9)
          page = request.GET.get('page')
          paged_products = paginator.get_page(page)
          product_count = products.count()

      if is_valid_queryparam(price_max):
          if sort_by == "l2h":
              products = Product.objects.filter(price__lte=price_max).order_by('price')
          elif sort_by == "h2l":
              products = Product.objects.filter(price__lte=price_max).order_by('-price')
          paginator = Paginator(products, 9)
          page = request.GET.get('page')
          paged_products = paginator.get_page(page)
          product_count = products.count()
  else:   
      products = Product.objects.all().order_by('price')
      paginator = Paginator(products, 9)
      page = request.GET.get('page')
      paged_products = paginator.get_page(page)
      product_count = products.count()

  context={
      'products': paged_products,
      'product_count': product_count,
  }
  return render(request, 'store.html', context)

If I try to filter based on the min and max price it works, but when I'm trying to sort or if there is no filter apply I get this UnboundLocalError:

UnboundLocalError at /store/
local variable 'paged_products' referenced before assignment
Request Method: GET
Request URL:    http://127.0.0.1:8000/store/?sort=h2l
Django Version: 3.1
Exception Type: UnboundLocalError
Exception Value:    
local variable 'paged_products' referenced before assignment
Exception Location: C:\Users\store\views.py, line 299, in filter

I researched Django documentation, google and SO but I did not find a solution. I have tried to rearrange the code, declare the variables as global, exclude 'sort' from the request.GET params, and no success.

CodePudding user response:

You are getting UnboundLocalError error because you have not defined an else block for if is_valid_queryparam(price_min): and if is_valid_queryparam(price_max): as well as for sort by. As a result when you don't apply a filter paged_products and product_count never gets defined and raising UnboundLocalError at /store/ local variable 'paged_products' referenced before assignment.

Try the following code below that will eliminate the issue as well as will optimize the code.

def is_valid_queryparam(param):
    return param != '' and param is not None

def filter(request):
    if request.GET:
        price_min = request.GET.get('priceMin')
        price_max = request.GET.get('priceMax')
        sort_by = request.GET.get("sort", "l2h")

        if is_valid_queryparam(price_min):
            if sort_by == "l2h":
                products = Product.objects.filter(price__gte=price_min).order_by('price')
            elif sort_by == "h2l":
                products = Product.objects.filter(price__gte=price_min).order_by('-price')
            else:
                products = Product.objects.filter(price__gte=price_min)
        else:
            products = Product.objects.all().order_by('price')

        if is_valid_queryparam(price_max):
            if sort_by == "l2h":
                products = Product.objects.filter(price__lte=price_max).order_by('price')
            elif sort_by == "h2l":
                products = Product.objects.filter(price__lte=price_max).order_by('-price')
            else:
                products = Product.objects.filter(price__lte=price_max)
        else:
            products = Product.objects.all().order_by('price')
    else:
        products = Product.objects.all().order_by('price')

    paginator = Paginator(products, 9)
    page = request.GET.get('page')
    paged_products = paginator.get_page(page)
    product_count = products.count()

    context = {
        'products': paged_products,
        'product_count': product_count,
    }
    return render(request, 'store.html', context)

CodePudding user response:

I slightly changed Nahidur Rahman's code in order for the minimum price filter to work, it is necessary to take the query from the minimum price and apply the filter for the maximum price.

def is_valid_queryparam(param):
    return param != '' and param is not None

def filter(request):
if request.GET:
    price_min = request.GET.get('priceMin')
    price_max = request.GET.get('priceMax')
    sort_by = request.GET.get("sort", "l2h")

    if is_valid_queryparam(price_min):
        if sort_by == "l2h":
            products = Product.objects.filter(price__gte=price_min).order_by('price')
        elif sort_by == "h2l":
            products = Product.objects.filter(price__gte=price_min).order_by('-price')
        else:
            products = Product.objects.filter(price__gte=price_min)
    else:
        products = Product.objects.all().order_by('price')

    if is_valid_queryparam(price_max):
        if sort_by == "l2h":
            products = products.filter(price__lte=price_max).order_by('price')
        elif sort_by == "h2l":
            products = products.filter(price__lte=price_max).order_by('-price')
        else:
            products = products.filter(price__lte=price_max)
    else:
        products = products
else:
    products = Product.objects.all().order_by('price')

paginator = Paginator(products, 9)
page = request.GET.get('page')
paged_products = paginator.get_page(page)
product_count = products.count()

context = {
    'products': paged_products,
    'product_count': product_count,
}
return render(request, 'store.html', context)
  • Related