We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Improve "Sort by" label appearance
"Sort by" label is rendered differently on the `demo` branch and on `master`. This is probably due to the fact that on demo it's rendered as React component and on master as Django template. However, we have to make sure that the markup and styling is the same in both cases.

Demo:
![image](https://user-images.githubusercontent.com/5421321/33717732-59419f6e-db5b-11e7-93a0-e0baada82979.png)
- missing space between the colon and the field name

Master:
![image](https://user-images.githubusercontent.com/5421321/33717836-a86de732-db5b-11e7-9508-92a620a9699a.png)
- missing colon
- too much space between the label and the icon

Also, I think that the arrow icon could be a little bit smaller; currently it's visually too heavy compared to the text.



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `saleor/core/utils/filters.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 from django_countries import countries
4 from django.db.models import Q
5 
6 
7 def get_sort_by_choices(filter_set):
8     return [(choice[0], choice[1].lower()) for choice in
9             filter_set.filters['sort_by'].field.choices[1::2]]
10 
11 
12 def get_now_sorted_by(filter_set, fields, default_sort='name'):
13     sort_by = filter_set.form.cleaned_data.get('sort_by')
14     if sort_by:
15         sort_by = fields[sort_by[0].strip('-')]
16     else:
17         sort_by = fields[default_sort]
18     return sort_by
19 
20 
21 def filter_by_customer(queryset, name, value):
22     return queryset.filter(
23         Q(email__icontains=value) |
24         Q(default_billing_address__first_name__icontains=value) |
25         Q(default_billing_address__last_name__icontains=value))
26 
27 
28 def filter_by_order_customer(queryset, name, value):
29     return queryset.filter(
30         Q(user__email__icontains=value) |
31         Q(user__default_billing_address__first_name__icontains=value) |
32         Q(user__default_billing_address__last_name__icontains=value))
33 
34 
35 def filter_by_location(queryset, name, value):
36     q = Q(default_billing_address__city__icontains=value)
37     q |= Q(default_billing_address__country__icontains=value)
38     country_codes = get_mapped_country_codes_from_search(value)
39     for code in country_codes:
40         q |= Q(default_billing_address__country__icontains=code)
41     return queryset.filter(q)
42 
43 
44 def get_mapped_country_codes_from_search(value):
45     country_codes = []
46     for code, country in dict(countries).items():
47         if value.lower() in country.lower():
48             country_codes.append(code)
49     return country_codes
50 
51 
52 def filter_by_date_range(queryset, name, value):
53     q = Q()
54     if value.start:
55         q = Q(start_date__gte=value.start)
56     if value.stop:
57         if value.start:
58             q |= Q(end_date__lte=value.stop)
59         else:
60             q = Q(end_date__lte=value.stop)
61     return queryset.filter(q)
62
```

Path: `saleor/product/views.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import datetime
4 import json
5 
6 from django.conf import settings
7 from django.http import HttpResponsePermanentRedirect, JsonResponse
8 from django.shortcuts import get_object_or_404, redirect
9 from django.template.response import TemplateResponse
10 from django.urls import reverse
11 
12 from ..cart.utils import set_cart_cookie
13 from ..core.utils import get_paginator_items, serialize_decimal
14 from ..core.utils.filters import get_now_sorted_by, get_sort_by_choices
15 from .filters import ProductFilter, SORT_BY_FIELDS
16 from .models import Category
17 from .utils import (
18     get_availability, get_product_attributes_data, get_product_images,
19     get_variant_picker_data, handle_cart_form, product_json_ld,
20     products_for_cart, products_with_availability, products_with_details)
21 
22 
23 def product_details(request, slug, product_id, form=None):
24     """Product details page
25 
26     The following variables are available to the template:
27 
28     product:
29         The Product instance itself.
30 
31     is_visible:
32         Whether the product is visible to regular users (for cases when an
33         admin is previewing a product before publishing).
34 
35     form:
36         The add-to-cart form.
37 
38     price_range:
39         The PriceRange for the product including all discounts.
40 
41     undiscounted_price_range:
42         The PriceRange excluding all discounts.
43 
44     discount:
45         Either a Price instance equal to the discount value or None if no
46         discount was available.
47 
48     local_price_range:
49         The same PriceRange from price_range represented in user's local
50         currency. The value will be None if exchange rate is not available or
51         the local currency is the same as site's default currency.
52     """
53     products = products_with_details(user=request.user)
54     product = get_object_or_404(products, id=product_id)
55     if product.get_slug() != slug:
56         return HttpResponsePermanentRedirect(product.get_absolute_url())
57     today = datetime.date.today()
58     is_visible = (
59         product.available_on is None or product.available_on <= today)
60     if form is None:
61         form = handle_cart_form(request, product, create_cart=False)[0]
62     availability = get_availability(product, discounts=request.discounts,
63                                     local_currency=request.currency)
64     product_images = get_product_images(product)
65     variant_picker_data = get_variant_picker_data(
66         product, request.discounts, request.currency)
67     product_attributes = get_product_attributes_data(product)
68     show_variant_picker = all([v.attributes for v in product.variants.all()])
69     json_ld_data = product_json_ld(product, availability, product_attributes)
70     return TemplateResponse(
71         request, 'product/details.html',
72         {'is_visible': is_visible,
73          'form': form,
74          'availability': availability,
75          'product': product,
76          'product_attributes': product_attributes,
77          'product_images': product_images,
78          'show_variant_picker': show_variant_picker,
79          'variant_picker_data': json.dumps(
80              variant_picker_data, default=serialize_decimal),
81          'json_ld_product_data': json.dumps(
82              json_ld_data, default=serialize_decimal)})
83 
84 
85 def product_add_to_cart(request, slug, product_id):
86     # types: (int, str, dict) -> None
87 
88     if not request.method == 'POST':
89         return redirect(reverse(
90             'product:details',
91             kwargs={'product_id': product_id, 'slug': slug}))
92 
93     products = products_for_cart(user=request.user)
94     product = get_object_or_404(products, pk=product_id)
95     form, cart = handle_cart_form(request, product, create_cart=True)
96     if form.is_valid():
97         form.save()
98         if request.is_ajax():
99             response = JsonResponse({'next': reverse('cart:index')}, status=200)
100         else:
101             response = redirect('cart:index')
102     else:
103         if request.is_ajax():
104             response = JsonResponse({'error': form.errors}, status=400)
105         else:
106             response = product_details(request, slug, product_id, form)
107     if not request.user.is_authenticated:
108         set_cart_cookie(cart, response)
109     return response
110 
111 
112 def category_index(request, path, category_id):
113     category = get_object_or_404(Category, id=category_id)
114     actual_path = category.get_full_path()
115     if actual_path != path:
116         return redirect('product:category', permanent=True, path=actual_path,
117                         category_id=category_id)
118     products = (products_with_details(user=request.user)
119                 .filter(categories__id=category.id)
120                 .order_by('name'))
121     product_filter = ProductFilter(
122         request.GET, queryset=products, category=category)
123     products_paginated = get_paginator_items(
124         product_filter.qs, settings.PAGINATE_BY, request.GET.get('page'))
125     products_and_availability = list(products_with_availability(
126         products_paginated, request.discounts, request.currency))
127     now_sorted_by = get_now_sorted_by(product_filter, SORT_BY_FIELDS)
128     arg_sort_by = request.GET.get('sort_by')
129     is_descending = arg_sort_by.startswith('-') if arg_sort_by else False
130     ctx = {'category': category, 'filter': product_filter,
131            'products': products_and_availability,
132            'products_paginated': products_paginated,
133            'sort_by_choices': get_sort_by_choices(product_filter),
134            'now_sorted_by': now_sorted_by,
135            'is_descending': is_descending}
136     return TemplateResponse(request, 'category/index.html', ctx)
137
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/saleor/core/utils/filters.py b/saleor/core/utils/filters.py
--- a/saleor/core/utils/filters.py
+++ b/saleor/core/utils/filters.py
@@ -9,12 +9,12 @@
             filter_set.filters['sort_by'].field.choices[1::2]]
 
 
-def get_now_sorted_by(filter_set, fields, default_sort='name'):
+def get_now_sorted_by(filter_set, default_sort='name'):
     sort_by = filter_set.form.cleaned_data.get('sort_by')
     if sort_by:
-        sort_by = fields[sort_by[0].strip('-')]
+        sort_by = sort_by[0].strip('-')
     else:
-        sort_by = fields[default_sort]
+        sort_by = default_sort
     return sort_by
 
 
diff --git a/saleor/product/views.py b/saleor/product/views.py
--- a/saleor/product/views.py
+++ b/saleor/product/views.py
@@ -124,7 +124,7 @@
         product_filter.qs, settings.PAGINATE_BY, request.GET.get('page'))
     products_and_availability = list(products_with_availability(
         products_paginated, request.discounts, request.currency))
-    now_sorted_by = get_now_sorted_by(product_filter, SORT_BY_FIELDS)
+    now_sorted_by = get_now_sorted_by(product_filter)
     arg_sort_by = request.GET.get('sort_by')
     is_descending = arg_sort_by.startswith('-') if arg_sort_by else False
     ctx = {'category': category, 'filter': product_filter,

{"golden_diff": "diff --git a/saleor/core/utils/filters.py b/saleor/core/utils/filters.py\n--- a/saleor/core/utils/filters.py\n+++ b/saleor/core/utils/filters.py\n@@ -9,12 +9,12 @@\n             filter_set.filters['sort_by'].field.choices[1::2]]\n \n \n-def get_now_sorted_by(filter_set, fields, default_sort='name'):\n+def get_now_sorted_by(filter_set, default_sort='name'):\n     sort_by = filter_set.form.cleaned_data.get('sort_by')\n     if sort_by:\n-        sort_by = fields[sort_by[0].strip('-')]\n+        sort_by = sort_by[0].strip('-')\n     else:\n-        sort_by = fields[default_sort]\n+        sort_by = default_sort\n     return sort_by\n \n \ndiff --git a/saleor/product/views.py b/saleor/product/views.py\n--- a/saleor/product/views.py\n+++ b/saleor/product/views.py\n@@ -124,7 +124,7 @@\n         product_filter.qs, settings.PAGINATE_BY, request.GET.get('page'))\n     products_and_availability = list(products_with_availability(\n         products_paginated, request.discounts, request.currency))\n-    now_sorted_by = get_now_sorted_by(product_filter, SORT_BY_FIELDS)\n+    now_sorted_by = get_now_sorted_by(product_filter)\n     arg_sort_by = request.GET.get('sort_by')\n     is_descending = arg_sort_by.startswith('-') if arg_sort_by else False\n     ctx = {'category': category, 'filter': product_filter,\n", "issue": "Improve \"Sort by\" label appearance\n\"Sort by\" label is rendered differently on the `demo` branch and on `master`. This is probably due to the fact that on demo it's rendered as React component and on master as Django template. However, we have to make sure that the markup and styling is the same in both cases.\r\n\r\nDemo:\r\n![image](https://user-images.githubusercontent.com/5421321/33717732-59419f6e-db5b-11e7-93a0-e0baada82979.png)\r\n- missing space between the colon and the field name\r\n\r\nMaster:\r\n![image](https://user-images.githubusercontent.com/5421321/33717836-a86de732-db5b-11e7-9508-92a620a9699a.png)\r\n- missing colon\r\n- too much space between the label and the icon\r\n\r\nAlso, I think that the arrow icon could be a little bit smaller; currently it's visually too heavy compared to the text.\r\n\r\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nfrom django_countries import countries\nfrom django.db.models import Q\n\n\ndef get_sort_by_choices(filter_set):\n    return [(choice[0], choice[1].lower()) for choice in\n            filter_set.filters['sort_by'].field.choices[1::2]]\n\n\ndef get_now_sorted_by(filter_set, fields, default_sort='name'):\n    sort_by = filter_set.form.cleaned_data.get('sort_by')\n    if sort_by:\n        sort_by = fields[sort_by[0].strip('-')]\n    else:\n        sort_by = fields[default_sort]\n    return sort_by\n\n\ndef filter_by_customer(queryset, name, value):\n    return queryset.filter(\n        Q(email__icontains=value) |\n        Q(default_billing_address__first_name__icontains=value) |\n        Q(default_billing_address__last_name__icontains=value))\n\n\ndef filter_by_order_customer(queryset, name, value):\n    return queryset.filter(\n        Q(user__email__icontains=value) |\n        Q(user__default_billing_address__first_name__icontains=value) |\n        Q(user__default_billing_address__last_name__icontains=value))\n\n\ndef filter_by_location(queryset, name, value):\n    q = Q(default_billing_address__city__icontains=value)\n    q |= Q(default_billing_address__country__icontains=value)\n    country_codes = get_mapped_country_codes_from_search(value)\n    for code in country_codes:\n        q |= Q(default_billing_address__country__icontains=code)\n    return queryset.filter(q)\n\n\ndef get_mapped_country_codes_from_search(value):\n    country_codes = []\n    for code, country in dict(countries).items():\n        if value.lower() in country.lower():\n            country_codes.append(code)\n    return country_codes\n\n\ndef filter_by_date_range(queryset, name, value):\n    q = Q()\n    if value.start:\n        q = Q(start_date__gte=value.start)\n    if value.stop:\n        if value.start:\n            q |= Q(end_date__lte=value.stop)\n        else:\n            q = Q(end_date__lte=value.stop)\n    return queryset.filter(q)\n", "path": "saleor/core/utils/filters.py"}, {"content": "from __future__ import unicode_literals\n\nimport datetime\nimport json\n\nfrom django.conf import settings\nfrom django.http import HttpResponsePermanentRedirect, JsonResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.template.response import TemplateResponse\nfrom django.urls import reverse\n\nfrom ..cart.utils import set_cart_cookie\nfrom ..core.utils import get_paginator_items, serialize_decimal\nfrom ..core.utils.filters import get_now_sorted_by, get_sort_by_choices\nfrom .filters import ProductFilter, SORT_BY_FIELDS\nfrom .models import Category\nfrom .utils import (\n    get_availability, get_product_attributes_data, get_product_images,\n    get_variant_picker_data, handle_cart_form, product_json_ld,\n    products_for_cart, products_with_availability, products_with_details)\n\n\ndef product_details(request, slug, product_id, form=None):\n    \"\"\"Product details page\n\n    The following variables are available to the template:\n\n    product:\n        The Product instance itself.\n\n    is_visible:\n        Whether the product is visible to regular users (for cases when an\n        admin is previewing a product before publishing).\n\n    form:\n        The add-to-cart form.\n\n    price_range:\n        The PriceRange for the product including all discounts.\n\n    undiscounted_price_range:\n        The PriceRange excluding all discounts.\n\n    discount:\n        Either a Price instance equal to the discount value or None if no\n        discount was available.\n\n    local_price_range:\n        The same PriceRange from price_range represented in user's local\n        currency. The value will be None if exchange rate is not available or\n        the local currency is the same as site's default currency.\n    \"\"\"\n    products = products_with_details(user=request.user)\n    product = get_object_or_404(products, id=product_id)\n    if product.get_slug() != slug:\n        return HttpResponsePermanentRedirect(product.get_absolute_url())\n    today = datetime.date.today()\n    is_visible = (\n        product.available_on is None or product.available_on <= today)\n    if form is None:\n        form = handle_cart_form(request, product, create_cart=False)[0]\n    availability = get_availability(product, discounts=request.discounts,\n                                    local_currency=request.currency)\n    product_images = get_product_images(product)\n    variant_picker_data = get_variant_picker_data(\n        product, request.discounts, request.currency)\n    product_attributes = get_product_attributes_data(product)\n    show_variant_picker = all([v.attributes for v in product.variants.all()])\n    json_ld_data = product_json_ld(product, availability, product_attributes)\n    return TemplateResponse(\n        request, 'product/details.html',\n        {'is_visible': is_visible,\n         'form': form,\n         'availability': availability,\n         'product': product,\n         'product_attributes': product_attributes,\n         'product_images': product_images,\n         'show_variant_picker': show_variant_picker,\n         'variant_picker_data': json.dumps(\n             variant_picker_data, default=serialize_decimal),\n         'json_ld_product_data': json.dumps(\n             json_ld_data, default=serialize_decimal)})\n\n\ndef product_add_to_cart(request, slug, product_id):\n    # types: (int, str, dict) -> None\n\n    if not request.method == 'POST':\n        return redirect(reverse(\n            'product:details',\n            kwargs={'product_id': product_id, 'slug': slug}))\n\n    products = products_for_cart(user=request.user)\n    product = get_object_or_404(products, pk=product_id)\n    form, cart = handle_cart_form(request, product, create_cart=True)\n    if form.is_valid():\n        form.save()\n        if request.is_ajax():\n            response = JsonResponse({'next': reverse('cart:index')}, status=200)\n        else:\n            response = redirect('cart:index')\n    else:\n        if request.is_ajax():\n            response = JsonResponse({'error': form.errors}, status=400)\n        else:\n            response = product_details(request, slug, product_id, form)\n    if not request.user.is_authenticated:\n        set_cart_cookie(cart, response)\n    return response\n\n\ndef category_index(request, path, category_id):\n    category = get_object_or_404(Category, id=category_id)\n    actual_path = category.get_full_path()\n    if actual_path != path:\n        return redirect('product:category', permanent=True, path=actual_path,\n                        category_id=category_id)\n    products = (products_with_details(user=request.user)\n                .filter(categories__id=category.id)\n                .order_by('name'))\n    product_filter = ProductFilter(\n        request.GET, queryset=products, category=category)\n    products_paginated = get_paginator_items(\n        product_filter.qs, settings.PAGINATE_BY, request.GET.get('page'))\n    products_and_availability = list(products_with_availability(\n        products_paginated, request.discounts, request.currency))\n    now_sorted_by = get_now_sorted_by(product_filter, SORT_BY_FIELDS)\n    arg_sort_by = request.GET.get('sort_by')\n    is_descending = arg_sort_by.startswith('-') if arg_sort_by else False\n    ctx = {'category': category, 'filter': product_filter,\n           'products': products_and_availability,\n           'products_paginated': products_paginated,\n           'sort_by_choices': get_sort_by_choices(product_filter),\n           'now_sorted_by': now_sorted_by,\n           'is_descending': is_descending}\n    return TemplateResponse(request, 'category/index.html', ctx)\n", "path": "saleor/product/views.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nfrom django_countries import countries\nfrom django.db.models import Q\n\n\ndef get_sort_by_choices(filter_set):\n    return [(choice[0], choice[1].lower()) for choice in\n            filter_set.filters['sort_by'].field.choices[1::2]]\n\n\ndef get_now_sorted_by(filter_set, default_sort='name'):\n    sort_by = filter_set.form.cleaned_data.get('sort_by')\n    if sort_by:\n        sort_by = sort_by[0].strip('-')\n    else:\n        sort_by = default_sort\n    return sort_by\n\n\ndef filter_by_customer(queryset, name, value):\n    return queryset.filter(\n        Q(email__icontains=value) |\n        Q(default_billing_address__first_name__icontains=value) |\n        Q(default_billing_address__last_name__icontains=value))\n\n\ndef filter_by_order_customer(queryset, name, value):\n    return queryset.filter(\n        Q(user__email__icontains=value) |\n        Q(user__default_billing_address__first_name__icontains=value) |\n        Q(user__default_billing_address__last_name__icontains=value))\n\n\ndef filter_by_location(queryset, name, value):\n    q = Q(default_billing_address__city__icontains=value)\n    q |= Q(default_billing_address__country__icontains=value)\n    country_codes = get_mapped_country_codes_from_search(value)\n    for code in country_codes:\n        q |= Q(default_billing_address__country__icontains=code)\n    return queryset.filter(q)\n\n\ndef get_mapped_country_codes_from_search(value):\n    country_codes = []\n    for code, country in dict(countries).items():\n        if value.lower() in country.lower():\n            country_codes.append(code)\n    return country_codes\n\n\ndef filter_by_date_range(queryset, name, value):\n    q = Q()\n    if value.start:\n        q = Q(start_date__gte=value.start)\n    if value.stop:\n        if value.start:\n            q |= Q(end_date__lte=value.stop)\n        else:\n            q = Q(end_date__lte=value.stop)\n    return queryset.filter(q)\n", "path": "saleor/core/utils/filters.py"}, {"content": "from __future__ import unicode_literals\n\nimport datetime\nimport json\n\nfrom django.conf import settings\nfrom django.http import HttpResponsePermanentRedirect, JsonResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.template.response import TemplateResponse\nfrom django.urls import reverse\n\nfrom ..cart.utils import set_cart_cookie\nfrom ..core.utils import get_paginator_items, serialize_decimal\nfrom ..core.utils.filters import get_now_sorted_by, get_sort_by_choices\nfrom .filters import ProductFilter, SORT_BY_FIELDS\nfrom .models import Category\nfrom .utils import (\n    get_availability, get_product_attributes_data, get_product_images,\n    get_variant_picker_data, handle_cart_form, product_json_ld,\n    products_for_cart, products_with_availability, products_with_details)\n\n\ndef product_details(request, slug, product_id, form=None):\n    \"\"\"Product details page\n\n    The following variables are available to the template:\n\n    product:\n        The Product instance itself.\n\n    is_visible:\n        Whether the product is visible to regular users (for cases when an\n        admin is previewing a product before publishing).\n\n    form:\n        The add-to-cart form.\n\n    price_range:\n        The PriceRange for the product including all discounts.\n\n    undiscounted_price_range:\n        The PriceRange excluding all discounts.\n\n    discount:\n        Either a Price instance equal to the discount value or None if no\n        discount was available.\n\n    local_price_range:\n        The same PriceRange from price_range represented in user's local\n        currency. The value will be None if exchange rate is not available or\n        the local currency is the same as site's default currency.\n    \"\"\"\n    products = products_with_details(user=request.user)\n    product = get_object_or_404(products, id=product_id)\n    if product.get_slug() != slug:\n        return HttpResponsePermanentRedirect(product.get_absolute_url())\n    today = datetime.date.today()\n    is_visible = (\n        product.available_on is None or product.available_on <= today)\n    if form is None:\n        form = handle_cart_form(request, product, create_cart=False)[0]\n    availability = get_availability(product, discounts=request.discounts,\n                                    local_currency=request.currency)\n    product_images = get_product_images(product)\n    variant_picker_data = get_variant_picker_data(\n        product, request.discounts, request.currency)\n    product_attributes = get_product_attributes_data(product)\n    show_variant_picker = all([v.attributes for v in product.variants.all()])\n    json_ld_data = product_json_ld(product, availability, product_attributes)\n    return TemplateResponse(\n        request, 'product/details.html',\n        {'is_visible': is_visible,\n         'form': form,\n         'availability': availability,\n         'product': product,\n         'product_attributes': product_attributes,\n         'product_images': product_images,\n         'show_variant_picker': show_variant_picker,\n         'variant_picker_data': json.dumps(\n             variant_picker_data, default=serialize_decimal),\n         'json_ld_product_data': json.dumps(\n             json_ld_data, default=serialize_decimal)})\n\n\ndef product_add_to_cart(request, slug, product_id):\n    # types: (int, str, dict) -> None\n\n    if not request.method == 'POST':\n        return redirect(reverse(\n            'product:details',\n            kwargs={'product_id': product_id, 'slug': slug}))\n\n    products = products_for_cart(user=request.user)\n    product = get_object_or_404(products, pk=product_id)\n    form, cart = handle_cart_form(request, product, create_cart=True)\n    if form.is_valid():\n        form.save()\n        if request.is_ajax():\n            response = JsonResponse({'next': reverse('cart:index')}, status=200)\n        else:\n            response = redirect('cart:index')\n    else:\n        if request.is_ajax():\n            response = JsonResponse({'error': form.errors}, status=400)\n        else:\n            response = product_details(request, slug, product_id, form)\n    if not request.user.is_authenticated:\n        set_cart_cookie(cart, response)\n    return response\n\n\ndef category_index(request, path, category_id):\n    category = get_object_or_404(Category, id=category_id)\n    actual_path = category.get_full_path()\n    if actual_path != path:\n        return redirect('product:category', permanent=True, path=actual_path,\n                        category_id=category_id)\n    products = (products_with_details(user=request.user)\n                .filter(categories__id=category.id)\n                .order_by('name'))\n    product_filter = ProductFilter(\n        request.GET, queryset=products, category=category)\n    products_paginated = get_paginator_items(\n        product_filter.qs, settings.PAGINATE_BY, request.GET.get('page'))\n    products_and_availability = list(products_with_availability(\n        products_paginated, request.discounts, request.currency))\n    now_sorted_by = get_now_sorted_by(product_filter)\n    arg_sort_by = request.GET.get('sort_by')\n    is_descending = arg_sort_by.startswith('-') if arg_sort_by else False\n    ctx = {'category': category, 'filter': product_filter,\n           'products': products_and_availability,\n           'products_paginated': products_paginated,\n           'sort_by_choices': get_sort_by_choices(product_filter),\n           'now_sorted_by': now_sorted_by,\n           'is_descending': is_descending}\n    return TemplateResponse(request, 'category/index.html', ctx)\n", "path": "saleor/product/views.py"}]}