We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Calling get_price_range() on an empty item range
On the product detail page backend doesn't check existence of product variants.
If the product requires variants, but they don't exist, Django throws an exception `Calling get_price_range() on an empty item range`.

--- 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/product/utils.py`
Content:
```
1 from collections import namedtuple
2 
3 from ..cart.utils import get_cart_from_request, get_or_create_cart_from_request
4 from ..core.utils import to_local_currency
5 from .forms import get_form_class_for_product
6 from .models.utils import get_attributes_display_map
7 from .models import Product
8 
9 
10 def products_visible_to_user(user):
11     if (user.is_authenticated() and
12             user.is_active and user.is_staff):
13         return Product.objects.all()
14     else:
15         return Product.objects.get_available_products()
16 
17 
18 def products_with_details(user):
19     products = products_visible_to_user(user)
20     products = products.prefetch_related('categories', 'images',
21                                          'variants__stock',
22                                          'variants__variant_images__image',
23                                          'attributes__values',
24                                          'product_class__variant_attributes__values',
25                                          'product_class__product_attributes__values')
26     return products
27 
28 
29 def get_product_images(product):
30     """
31     Returns list of product images that will be placed in product gallery
32     """
33     return list(product.images.all())
34 
35 
36 def products_with_availability(products, discounts, local_currency):
37     for product in products:
38         yield product, get_availability(product, discounts, local_currency)
39 
40 
41 ProductAvailability = namedtuple(
42     'ProductAvailability', (
43         'available', 'price_range', 'price_range_undiscounted', 'discount',
44         'price_range_local_currency', 'discount_local_currency'))
45 
46 
47 def get_availability(product, discounts=None, local_currency=None):
48     # In default currency
49     price_range = product.get_price_range(discounts=discounts)
50     undiscounted = product.get_price_range()
51     if undiscounted.min_price > price_range.min_price:
52         discount = undiscounted.min_price - price_range.min_price
53     else:
54         discount = None
55 
56     # Local currency
57     if local_currency:
58         price_range_local = to_local_currency(
59             price_range, local_currency)
60         undiscounted_local = to_local_currency(
61             undiscounted, local_currency)
62         if (undiscounted_local and
63                 undiscounted_local.min_price > price_range_local.min_price):
64             discount_local_currency = (
65                 undiscounted_local.min_price - price_range_local.min_price)
66         else:
67             discount_local_currency = None
68     else:
69         price_range_local = None
70         discount_local_currency = None
71 
72     is_available = product.is_in_stock() and product.is_available()
73 
74     return ProductAvailability(
75         available=is_available,
76         price_range=price_range,
77         price_range_undiscounted=undiscounted,
78         discount=discount,
79         price_range_local_currency=price_range_local,
80         discount_local_currency=discount_local_currency)
81 
82 
83 def handle_cart_form(request, product, create_cart=False):
84     if create_cart:
85         cart = get_or_create_cart_from_request(request)
86     else:
87         cart = get_cart_from_request(request)
88 
89     form_class = get_form_class_for_product(product)
90     form = form_class(cart=cart, product=product,
91                       data=request.POST or None, discounts=request.discounts)
92     return form, cart
93 
94 
95 def products_for_cart(user):
96     products = products_visible_to_user(user)
97     products = products.prefetch_related(
98         'variants', 'variants__variant_images__image')
99     return products
100 
101 
102 def get_variant_picker_data(product, discounts=None):
103     availability = get_availability(product, discounts)
104     variants = product.variants.all()
105     data = {'variantAttributes': [], 'variants': []}
106 
107     variant_attributes = product.product_class.variant_attributes.all()
108     for attribute in variant_attributes:
109         data['variantAttributes'].append({
110             'pk': attribute.pk,
111             'display': attribute.display,
112             'name': attribute.name,
113             'values': [{'pk': value.pk, 'display': value.display}
114                        for value in attribute.values.all()]})
115 
116     for variant in variants:
117         price = variant.get_price_per_item(discounts)
118         price_undiscounted = variant.get_price_per_item()
119         variant_data = {
120             'id': variant.id,
121             'price': price.gross,
122             'priceUndiscounted': price_undiscounted.gross,
123             'currency': price.currency,
124             'attributes': variant.attributes}
125         data['variants'].append(variant_data)
126 
127     data['availability'] = {
128         'discount': price_as_dict(availability.discount),
129         'priceRange': price_range_as_dict(availability.price_range),
130         'priceRangeUndiscounted': price_range_as_dict(
131             availability.price_range_undiscounted)}
132     return data
133 
134 
135 def get_product_attributes_data(product):
136     attributes = product.product_class.product_attributes.all()
137     attributes_map = {attribute.pk: attribute for attribute in attributes}
138     values_map = get_attributes_display_map(product, attributes)
139     return {attributes_map.get(attr_pk): value_obj
140             for (attr_pk, value_obj) in values_map.items()}
141 
142 
143 def price_as_dict(price):
144     if not price:
145         return {}
146     return {'currency': price.currency,
147             'gross': price.gross,
148             'net': price.net}
149 
150 
151 def price_range_as_dict(price_range):
152     return {'maxPrice': price_as_dict(price_range.max_price),
153             'minPrice': price_as_dict(price_range.min_price)}
154
```
--- 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/product/utils.py b/saleor/product/utils.py
--- a/saleor/product/utils.py
+++ b/saleor/product/utils.py
@@ -45,6 +45,15 @@
 
 
 def get_availability(product, discounts=None, local_currency=None):
+    if not product.variants.exists():
+        return ProductAvailability(
+            available=False,
+            price_range=None,
+            price_range_undiscounted=None,
+            discount=None,
+            price_range_local_currency=None,
+            discount_local_currency=None)
+
     # In default currency
     price_range = product.get_price_range(discounts=discounts)
     undiscounted = product.get_price_range()
@@ -142,12 +151,14 @@
 
 def price_as_dict(price):
     if not price:
-        return {}
+        return None
     return {'currency': price.currency,
             'gross': price.gross,
             'net': price.net}
 
 
 def price_range_as_dict(price_range):
+    if not price_range:
+        return None
     return {'maxPrice': price_as_dict(price_range.max_price),
             'minPrice': price_as_dict(price_range.min_price)}

{"golden_diff": "diff --git a/saleor/product/utils.py b/saleor/product/utils.py\n--- a/saleor/product/utils.py\n+++ b/saleor/product/utils.py\n@@ -45,6 +45,15 @@\n \n \n def get_availability(product, discounts=None, local_currency=None):\n+    if not product.variants.exists():\n+        return ProductAvailability(\n+            available=False,\n+            price_range=None,\n+            price_range_undiscounted=None,\n+            discount=None,\n+            price_range_local_currency=None,\n+            discount_local_currency=None)\n+\n     # In default currency\n     price_range = product.get_price_range(discounts=discounts)\n     undiscounted = product.get_price_range()\n@@ -142,12 +151,14 @@\n \n def price_as_dict(price):\n     if not price:\n-        return {}\n+        return None\n     return {'currency': price.currency,\n             'gross': price.gross,\n             'net': price.net}\n \n \n def price_range_as_dict(price_range):\n+    if not price_range:\n+        return None\n     return {'maxPrice': price_as_dict(price_range.max_price),\n             'minPrice': price_as_dict(price_range.min_price)}\n", "issue": "Calling get_price_range() on an empty item range\nOn the product detail page backend doesn't check existence of product variants.\r\nIf the product requires variants, but they don't exist, Django throws an exception `Calling get_price_range() on an empty item range`.\n", "before_files": [{"content": "from collections import namedtuple\n\nfrom ..cart.utils import get_cart_from_request, get_or_create_cart_from_request\nfrom ..core.utils import to_local_currency\nfrom .forms import get_form_class_for_product\nfrom .models.utils import get_attributes_display_map\nfrom .models import Product\n\n\ndef products_visible_to_user(user):\n    if (user.is_authenticated() and\n            user.is_active and user.is_staff):\n        return Product.objects.all()\n    else:\n        return Product.objects.get_available_products()\n\n\ndef products_with_details(user):\n    products = products_visible_to_user(user)\n    products = products.prefetch_related('categories', 'images',\n                                         'variants__stock',\n                                         'variants__variant_images__image',\n                                         'attributes__values',\n                                         'product_class__variant_attributes__values',\n                                         'product_class__product_attributes__values')\n    return products\n\n\ndef get_product_images(product):\n    \"\"\"\n    Returns list of product images that will be placed in product gallery\n    \"\"\"\n    return list(product.images.all())\n\n\ndef products_with_availability(products, discounts, local_currency):\n    for product in products:\n        yield product, get_availability(product, discounts, local_currency)\n\n\nProductAvailability = namedtuple(\n    'ProductAvailability', (\n        'available', 'price_range', 'price_range_undiscounted', 'discount',\n        'price_range_local_currency', 'discount_local_currency'))\n\n\ndef get_availability(product, discounts=None, local_currency=None):\n    # In default currency\n    price_range = product.get_price_range(discounts=discounts)\n    undiscounted = product.get_price_range()\n    if undiscounted.min_price > price_range.min_price:\n        discount = undiscounted.min_price - price_range.min_price\n    else:\n        discount = None\n\n    # Local currency\n    if local_currency:\n        price_range_local = to_local_currency(\n            price_range, local_currency)\n        undiscounted_local = to_local_currency(\n            undiscounted, local_currency)\n        if (undiscounted_local and\n                undiscounted_local.min_price > price_range_local.min_price):\n            discount_local_currency = (\n                undiscounted_local.min_price - price_range_local.min_price)\n        else:\n            discount_local_currency = None\n    else:\n        price_range_local = None\n        discount_local_currency = None\n\n    is_available = product.is_in_stock() and product.is_available()\n\n    return ProductAvailability(\n        available=is_available,\n        price_range=price_range,\n        price_range_undiscounted=undiscounted,\n        discount=discount,\n        price_range_local_currency=price_range_local,\n        discount_local_currency=discount_local_currency)\n\n\ndef handle_cart_form(request, product, create_cart=False):\n    if create_cart:\n        cart = get_or_create_cart_from_request(request)\n    else:\n        cart = get_cart_from_request(request)\n\n    form_class = get_form_class_for_product(product)\n    form = form_class(cart=cart, product=product,\n                      data=request.POST or None, discounts=request.discounts)\n    return form, cart\n\n\ndef products_for_cart(user):\n    products = products_visible_to_user(user)\n    products = products.prefetch_related(\n        'variants', 'variants__variant_images__image')\n    return products\n\n\ndef get_variant_picker_data(product, discounts=None):\n    availability = get_availability(product, discounts)\n    variants = product.variants.all()\n    data = {'variantAttributes': [], 'variants': []}\n\n    variant_attributes = product.product_class.variant_attributes.all()\n    for attribute in variant_attributes:\n        data['variantAttributes'].append({\n            'pk': attribute.pk,\n            'display': attribute.display,\n            'name': attribute.name,\n            'values': [{'pk': value.pk, 'display': value.display}\n                       for value in attribute.values.all()]})\n\n    for variant in variants:\n        price = variant.get_price_per_item(discounts)\n        price_undiscounted = variant.get_price_per_item()\n        variant_data = {\n            'id': variant.id,\n            'price': price.gross,\n            'priceUndiscounted': price_undiscounted.gross,\n            'currency': price.currency,\n            'attributes': variant.attributes}\n        data['variants'].append(variant_data)\n\n    data['availability'] = {\n        'discount': price_as_dict(availability.discount),\n        'priceRange': price_range_as_dict(availability.price_range),\n        'priceRangeUndiscounted': price_range_as_dict(\n            availability.price_range_undiscounted)}\n    return data\n\n\ndef get_product_attributes_data(product):\n    attributes = product.product_class.product_attributes.all()\n    attributes_map = {attribute.pk: attribute for attribute in attributes}\n    values_map = get_attributes_display_map(product, attributes)\n    return {attributes_map.get(attr_pk): value_obj\n            for (attr_pk, value_obj) in values_map.items()}\n\n\ndef price_as_dict(price):\n    if not price:\n        return {}\n    return {'currency': price.currency,\n            'gross': price.gross,\n            'net': price.net}\n\n\ndef price_range_as_dict(price_range):\n    return {'maxPrice': price_as_dict(price_range.max_price),\n            'minPrice': price_as_dict(price_range.min_price)}\n", "path": "saleor/product/utils.py"}], "after_files": [{"content": "from collections import namedtuple\n\nfrom ..cart.utils import get_cart_from_request, get_or_create_cart_from_request\nfrom ..core.utils import to_local_currency\nfrom .forms import get_form_class_for_product\nfrom .models.utils import get_attributes_display_map\nfrom .models import Product\n\n\ndef products_visible_to_user(user):\n    if (user.is_authenticated() and\n            user.is_active and user.is_staff):\n        return Product.objects.all()\n    else:\n        return Product.objects.get_available_products()\n\n\ndef products_with_details(user):\n    products = products_visible_to_user(user)\n    products = products.prefetch_related('categories', 'images',\n                                         'variants__stock',\n                                         'variants__variant_images__image',\n                                         'attributes__values',\n                                         'product_class__variant_attributes__values',\n                                         'product_class__product_attributes__values')\n    return products\n\n\ndef get_product_images(product):\n    \"\"\"\n    Returns list of product images that will be placed in product gallery\n    \"\"\"\n    return list(product.images.all())\n\n\ndef products_with_availability(products, discounts, local_currency):\n    for product in products:\n        yield product, get_availability(product, discounts, local_currency)\n\n\nProductAvailability = namedtuple(\n    'ProductAvailability', (\n        'available', 'price_range', 'price_range_undiscounted', 'discount',\n        'price_range_local_currency', 'discount_local_currency'))\n\n\ndef get_availability(product, discounts=None, local_currency=None):\n    if not product.variants.exists():\n        return ProductAvailability(\n            available=False,\n            price_range=None,\n            price_range_undiscounted=None,\n            discount=None,\n            price_range_local_currency=None,\n            discount_local_currency=None)\n\n    # In default currency\n    price_range = product.get_price_range(discounts=discounts)\n    undiscounted = product.get_price_range()\n    if undiscounted.min_price > price_range.min_price:\n        discount = undiscounted.min_price - price_range.min_price\n    else:\n        discount = None\n\n    # Local currency\n    if local_currency:\n        price_range_local = to_local_currency(\n            price_range, local_currency)\n        undiscounted_local = to_local_currency(\n            undiscounted, local_currency)\n        if (undiscounted_local and\n                undiscounted_local.min_price > price_range_local.min_price):\n            discount_local_currency = (\n                undiscounted_local.min_price - price_range_local.min_price)\n        else:\n            discount_local_currency = None\n    else:\n        price_range_local = None\n        discount_local_currency = None\n\n    is_available = product.is_in_stock() and product.is_available()\n\n    return ProductAvailability(\n        available=is_available,\n        price_range=price_range,\n        price_range_undiscounted=undiscounted,\n        discount=discount,\n        price_range_local_currency=price_range_local,\n        discount_local_currency=discount_local_currency)\n\n\ndef handle_cart_form(request, product, create_cart=False):\n    if create_cart:\n        cart = get_or_create_cart_from_request(request)\n    else:\n        cart = get_cart_from_request(request)\n\n    form_class = get_form_class_for_product(product)\n    form = form_class(cart=cart, product=product,\n                      data=request.POST or None, discounts=request.discounts)\n    return form, cart\n\n\ndef products_for_cart(user):\n    products = products_visible_to_user(user)\n    products = products.prefetch_related(\n        'variants', 'variants__variant_images__image')\n    return products\n\n\ndef get_variant_picker_data(product, discounts=None):\n    availability = get_availability(product, discounts)\n    variants = product.variants.all()\n    data = {'variantAttributes': [], 'variants': []}\n\n    variant_attributes = product.product_class.variant_attributes.all()\n    for attribute in variant_attributes:\n        data['variantAttributes'].append({\n            'pk': attribute.pk,\n            'display': attribute.display,\n            'name': attribute.name,\n            'values': [{'pk': value.pk, 'display': value.display}\n                       for value in attribute.values.all()]})\n\n    for variant in variants:\n        price = variant.get_price_per_item(discounts)\n        price_undiscounted = variant.get_price_per_item()\n        variant_data = {\n            'id': variant.id,\n            'price': price.gross,\n            'priceUndiscounted': price_undiscounted.gross,\n            'currency': price.currency,\n            'attributes': variant.attributes}\n        data['variants'].append(variant_data)\n\n    data['availability'] = {\n        'discount': price_as_dict(availability.discount),\n        'priceRange': price_range_as_dict(availability.price_range),\n        'priceRangeUndiscounted': price_range_as_dict(\n            availability.price_range_undiscounted)}\n    return data\n\n\ndef get_product_attributes_data(product):\n    attributes = product.product_class.product_attributes.all()\n    attributes_map = {attribute.pk: attribute for attribute in attributes}\n    values_map = get_attributes_display_map(product, attributes)\n    return {attributes_map.get(attr_pk): value_obj\n            for (attr_pk, value_obj) in values_map.items()}\n\n\ndef price_as_dict(price):\n    if not price:\n        return None\n    return {'currency': price.currency,\n            'gross': price.gross,\n            'net': price.net}\n\n\ndef price_range_as_dict(price_range):\n    if not price_range:\n        return None\n    return {'maxPrice': price_as_dict(price_range.max_price),\n            'minPrice': price_as_dict(price_range.min_price)}\n", "path": "saleor/product/utils.py"}]}