diff --git a/products/tests.py b/products/tests.py index 3881cd7..745875b 100644 --- a/products/tests.py +++ b/products/tests.py @@ -514,6 +514,12 @@ class ProductSearchTest(TestCase): self.assertEqual(response.status_code, 200) # load response data payload = response.json() + # check for expected fields in payload + self.assertIsNotNone(payload.get('filters')) + self.assertIsNotNone(payload.get('count')) + self.assertIsNotNone(payload.get('products')) + self.assertIsNotNone(payload.get('prices')) + # check for object creation self.assertEquals(len(payload['products']), len(expected_instances)) # check results ordered by rank @@ -524,6 +530,9 @@ class ProductSearchTest(TestCase): # check for filters self.assertNotEquals([], payload['filters']['tags']['singles']) self.assertTrue(len(payload['filters']['tags']) >= 2 ) + # check prices + self.assertTrue(payload['prices']['min'] <= payload['prices']['max']) + def test_anon_user_can_paginate_search(self): expected_instances = [ diff --git a/products/utils.py b/products/utils.py index 8cfe030..3d51ce6 100644 --- a/products/utils.py +++ b/products/utils.py @@ -2,6 +2,7 @@ import logging from django.db.models import Q from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector, TrigramSimilarity +from django.db.models import Max, Min from products.models import Product @@ -189,7 +190,12 @@ def find_related_products_v6(keyword, shipping_cost=None, discount=None, categor if price_max is not None: products_qs = products_qs.filter(price__lt=price_max) - return set(products_qs) + # get min_price and max_price + min_price = products_qs.aggregate(Min('price')) + max_price = products_qs.aggregate(Max('price')) + + + return set(products_qs), min_price, max_price def find_related_products_v4(keyword): diff --git a/products/views.py b/products/views.py index 8206444..8e45772 100644 --- a/products/views.py +++ b/products/views.py @@ -1,11 +1,7 @@ import logging import csv import datetime -import operator -from functools import reduce -from django.shortcuts import render -from django.conf import settings from django.db.models import Q from django.core import serializers @@ -157,6 +153,16 @@ def product_search(request): - category: string - tags: string - order: string (newest/oldest) + - price_min: int + - price_max: int + + In the response: + - filters + - count + - products + - price_min + - price_max + """ # capture query params q = request.GET.get('q', None) @@ -195,11 +201,22 @@ def product_search(request): try: # we collect our results here result_set = set() + # values for response + prices = { + 'min': None, + 'max': None, + } # split query string into single words chunks = q.split(' ') for chunk in chunks: - product_set = find_related_products_v6(chunk, shipping_cost, discount, category, tags, price_min, price_max) + product_set, min_price, max_price = find_related_products_v6(chunk, shipping_cost, discount, category, tags, price_min, price_max) + # update price values + # import ipdb; ipdb.set_trace() + if prices['min'] is None or min_price['price__min'] < prices['min']: + prices['min'] = min_price['price__min'] + if prices['max'] is None or max_price['price__max'] > prices['max']: + prices['max'] = max_price['price__max'] # add to result set result_set.update(product_set) # TODO: add search for entire phrase ??? @@ -218,6 +235,7 @@ def product_search(request): # order results by RANK ordered_products = sorted(result_list, key= lambda rank:rank.rank, reverse=True) + # extract max and min price values serializer = SearchResultSerializer(ordered_products, many=True) product_results = [dict(i) for i in serializer.data] total_results = len(product_results) @@ -231,6 +249,6 @@ def product_search(request): limit = int(limit) product_results = product_results[:limit] - return Response(data={"filters": filters, "count": total_results, "products": product_results}) + return Response(data={"filters": filters, "count": total_results, "products": product_results, 'prices': prices}) except Exception as e: return Response({"errors": {"details": str(e)}}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)