prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Refactor displaying success messages in the dashboard
  The code responsible for displaying success messages in the dashboard lives in [_messages.html](https://github.com/mirumee/saleor/blob/master/templates/dashboard/includes/_messages.html) template and mixes Django's templating language with JS which isn't very elegant. Instead, there should be a function written entirely in JS that would take care of rendering those messages with data passed from backend through `data-*` attributes.
  
  --- 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/dashboard/templatetags/utils.py`
  Content:
  ```
  1 from urllib.parse import urlencode
  2 
  3 from django import forms
  4 from django.template import Library
  5 from django_filters.fields import RangeField
  6 from versatileimagefield.widgets import VersatileImagePPOIClickWidget
  7 
  8 from ...product.utils import get_margin_for_variant, get_variant_costs_data
  9 from ..product.widgets import ImagePreviewWidget
  10 from .chips import (
  11     handle_default, handle_multiple_choice, handle_multiple_model_choice,
  12     handle_nullboolean, handle_range, handle_single_choice,
  13     handle_single_model_choice)
  14 
  15 register = Library()
  16 
  17 
  18 @register.simple_tag(takes_context=True)
  19 def construct_get_query(context, **params):
  20     request_get = context['request'].GET.dict()
  21     if not (request_get or params):
  22         return ''
  23     all_params = {}
  24     all_params.update(request_get)
  25     all_params.update(params)
  26     all_params.update(context.get('default_pagination_params', {}))
  27     return '?' + urlencode(all_params)
  28 
  29 
  30 @register.filter
  31 def is_versatile_image_ppoi_click_widget(field):
  32     '''
  33     This filter checks if image field widget is used when user wants to edit
  34     existing product image.
  35     '''
  36     return isinstance(field.field.widget, VersatileImagePPOIClickWidget)
  37 
  38 
  39 @register.filter
  40 def is_image_preview_widget(field):
  41     '''
  42     This filter checks if image field widget is used when user wants to add new
  43     product image.
  44     '''
  45     return isinstance(field.field.widget, ImagePreviewWidget)
  46 
  47 
  48 @register.inclusion_tag('dashboard/product/product_variant/_image_select.html')
  49 def render_image_choice(field):
  50     choices = zip(field, field.field.queryset)
  51     return {'field': field, 'choices_with_images': choices}
  52 
  53 
  54 @register.inclusion_tag('dashboard/includes/_pagination.html',
  55                         takes_context=True)
  56 def paginate(context, page_obj, num_of_pages=5):
  57     context['page_obj'] = page_obj
  58     context['n_forward'] = num_of_pages + 1
  59     context['n_backward'] = -num_of_pages - 1
  60     context['next_section'] = (2 * num_of_pages) + 1
  61     context['previous_section'] = (-2 * num_of_pages) - 1
  62     return context
  63 
  64 
  65 @register.simple_tag
  66 def margin_for_variant(stock):
  67     return get_margin_for_variant(stock)
  68 
  69 
  70 @register.simple_tag
  71 def margins_for_variant(variant):
  72     margins = get_variant_costs_data(variant)['margins']
  73     return margins
  74 
  75 
  76 @register.inclusion_tag('dashboard/includes/_filters.html', takes_context=True)
  77 def add_filters(context, filter_set, sort_by_filter_name='sort_by'):
  78     chips = []
  79     request_get = context['request'].GET.copy()
  80     for filter_name in filter_set.form.cleaned_data.keys():
  81         if filter_name == sort_by_filter_name:
  82             # Skip processing of sort_by filter, as it's rendered differently
  83             continue
  84 
  85         field = filter_set.form[filter_name]
  86         if field.value() not in ['', None]:
  87             if isinstance(field.field, forms.NullBooleanField):
  88                 items = handle_nullboolean(field, request_get)
  89             elif isinstance(field.field, forms.ModelMultipleChoiceField):
  90                 items = handle_multiple_model_choice(field, request_get)
  91             elif isinstance(field.field, forms.MultipleChoiceField):
  92                 items = handle_multiple_choice(field, request_get)
  93             elif isinstance(field.field, forms.ModelChoiceField):
  94                 items = handle_single_model_choice(field, request_get)
  95             elif isinstance(field.field, forms.ChoiceField):
  96                 items = handle_single_choice(field, request_get)
  97             elif isinstance(field.field, RangeField):
  98                 items = handle_range(field, request_get)
  99             else:
  100                 items = handle_default(field, request_get)
  101             chips.extend(items)
  102     return {
  103         'chips': chips, 'filter': filter_set, 'count': filter_set.qs.count(),
  104         'sort_by': request_get.get(sort_by_filter_name, None)}
  105
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/saleor/dashboard/templatetags/utils.py b/saleor/dashboard/templatetags/utils.py
  --- a/saleor/dashboard/templatetags/utils.py
  +++ b/saleor/dashboard/templatetags/utils.py
  @@ -1,3 +1,5 @@
  +from __future__ import unicode_literals
  +from json import dumps
   from urllib.parse import urlencode
   
   from django import forms
  @@ -102,3 +104,13 @@
       return {
           'chips': chips, 'filter': filter_set, 'count': filter_set.qs.count(),
           'sort_by': request_get.get(sort_by_filter_name, None)}
  +
  +
  +@register.simple_tag(takes_context=True)
  +def serialize_messages(context):
  +    """Serialize django.contrib.messages to JSON"""
  +    messages = context.get('messages', [])
  +    data = {}
  +    for i, message in enumerate(messages):
  +        data[i] = str(message)
  +    return dumps(data)
  
verification_info: {"golden_diff": "diff --git a/saleor/dashboard/templatetags/utils.py b/saleor/dashboard/templatetags/utils.py\n--- a/saleor/dashboard/templatetags/utils.py\n+++ b/saleor/dashboard/templatetags/utils.py\n@@ -1,3 +1,5 @@\n+from __future__ import unicode_literals\n+from json import dumps\n from urllib.parse import urlencode\n \n from django import forms\n@@ -102,3 +104,13 @@\n     return {\n         'chips': chips, 'filter': filter_set, 'count': filter_set.qs.count(),\n         'sort_by': request_get.get(sort_by_filter_name, None)}\n+\n+\n+@register.simple_tag(takes_context=True)\n+def serialize_messages(context):\n+    \"\"\"Serialize django.contrib.messages to JSON\"\"\"\n+    messages = context.get('messages', [])\n+    data = {}\n+    for i, message in enumerate(messages):\n+        data[i] = str(message)\n+    return dumps(data)\n", "issue": "Refactor displaying success messages in the dashboard\nThe code responsible for displaying success messages in the dashboard lives in [_messages.html](https://github.com/mirumee/saleor/blob/master/templates/dashboard/includes/_messages.html) template and mixes Django's templating language with JS which isn't very elegant. Instead, there should be a function written entirely in JS that would take care of rendering those messages with data passed from backend through `data-*` attributes.\n", "before_files": [{"content": "from urllib.parse import urlencode\n\nfrom django import forms\nfrom django.template import Library\nfrom django_filters.fields import RangeField\nfrom versatileimagefield.widgets import VersatileImagePPOIClickWidget\n\nfrom ...product.utils import get_margin_for_variant, get_variant_costs_data\nfrom ..product.widgets import ImagePreviewWidget\nfrom .chips import (\n    handle_default, handle_multiple_choice, handle_multiple_model_choice,\n    handle_nullboolean, handle_range, handle_single_choice,\n    handle_single_model_choice)\n\nregister = Library()\n\n\n@register.simple_tag(takes_context=True)\ndef construct_get_query(context, **params):\n    request_get = context['request'].GET.dict()\n    if not (request_get or params):\n        return ''\n    all_params = {}\n    all_params.update(request_get)\n    all_params.update(params)\n    all_params.update(context.get('default_pagination_params', {}))\n    return '?' + urlencode(all_params)\n\n\n@register.filter\ndef is_versatile_image_ppoi_click_widget(field):\n    '''\n    This filter checks if image field widget is used when user wants to edit\n    existing product image.\n    '''\n    return isinstance(field.field.widget, VersatileImagePPOIClickWidget)\n\n\n@register.filter\ndef is_image_preview_widget(field):\n    '''\n    This filter checks if image field widget is used when user wants to add new\n    product image.\n    '''\n    return isinstance(field.field.widget, ImagePreviewWidget)\n\n\n@register.inclusion_tag('dashboard/product/product_variant/_image_select.html')\ndef render_image_choice(field):\n    choices = zip(field, field.field.queryset)\n    return {'field': field, 'choices_with_images': choices}\n\n\n@register.inclusion_tag('dashboard/includes/_pagination.html',\n                        takes_context=True)\ndef paginate(context, page_obj, num_of_pages=5):\n    context['page_obj'] = page_obj\n    context['n_forward'] = num_of_pages + 1\n    context['n_backward'] = -num_of_pages - 1\n    context['next_section'] = (2 * num_of_pages) + 1\n    context['previous_section'] = (-2 * num_of_pages) - 1\n    return context\n\n\n@register.simple_tag\ndef margin_for_variant(stock):\n    return get_margin_for_variant(stock)\n\n\n@register.simple_tag\ndef margins_for_variant(variant):\n    margins = get_variant_costs_data(variant)['margins']\n    return margins\n\n\n@register.inclusion_tag('dashboard/includes/_filters.html', takes_context=True)\ndef add_filters(context, filter_set, sort_by_filter_name='sort_by'):\n    chips = []\n    request_get = context['request'].GET.copy()\n    for filter_name in filter_set.form.cleaned_data.keys():\n        if filter_name == sort_by_filter_name:\n            # Skip processing of sort_by filter, as it's rendered differently\n            continue\n\n        field = filter_set.form[filter_name]\n        if field.value() not in ['', None]:\n            if isinstance(field.field, forms.NullBooleanField):\n                items = handle_nullboolean(field, request_get)\n            elif isinstance(field.field, forms.ModelMultipleChoiceField):\n                items = handle_multiple_model_choice(field, request_get)\n            elif isinstance(field.field, forms.MultipleChoiceField):\n                items = handle_multiple_choice(field, request_get)\n            elif isinstance(field.field, forms.ModelChoiceField):\n                items = handle_single_model_choice(field, request_get)\n            elif isinstance(field.field, forms.ChoiceField):\n                items = handle_single_choice(field, request_get)\n            elif isinstance(field.field, RangeField):\n                items = handle_range(field, request_get)\n            else:\n                items = handle_default(field, request_get)\n            chips.extend(items)\n    return {\n        'chips': chips, 'filter': filter_set, 'count': filter_set.qs.count(),\n        'sort_by': request_get.get(sort_by_filter_name, None)}\n", "path": "saleor/dashboard/templatetags/utils.py"}], "after_files": [{"content": "from __future__ import unicode_literals\nfrom json import dumps\nfrom urllib.parse import urlencode\n\nfrom django import forms\nfrom django.template import Library\nfrom django_filters.fields import RangeField\nfrom versatileimagefield.widgets import VersatileImagePPOIClickWidget\n\nfrom ...product.utils import get_margin_for_variant, get_variant_costs_data\nfrom ..product.widgets import ImagePreviewWidget\nfrom .chips import (\n    handle_default, handle_multiple_choice, handle_multiple_model_choice,\n    handle_nullboolean, handle_range, handle_single_choice,\n    handle_single_model_choice)\n\nregister = Library()\n\n\n@register.simple_tag(takes_context=True)\ndef construct_get_query(context, **params):\n    request_get = context['request'].GET.dict()\n    if not (request_get or params):\n        return ''\n    all_params = {}\n    all_params.update(request_get)\n    all_params.update(params)\n    all_params.update(context.get('default_pagination_params', {}))\n    return '?' + urlencode(all_params)\n\n\n@register.filter\ndef is_versatile_image_ppoi_click_widget(field):\n    '''\n    This filter checks if image field widget is used when user wants to edit\n    existing product image.\n    '''\n    return isinstance(field.field.widget, VersatileImagePPOIClickWidget)\n\n\n@register.filter\ndef is_image_preview_widget(field):\n    '''\n    This filter checks if image field widget is used when user wants to add new\n    product image.\n    '''\n    return isinstance(field.field.widget, ImagePreviewWidget)\n\n\n@register.inclusion_tag('dashboard/product/product_variant/_image_select.html')\ndef render_image_choice(field):\n    choices = zip(field, field.field.queryset)\n    return {'field': field, 'choices_with_images': choices}\n\n\n@register.inclusion_tag('dashboard/includes/_pagination.html',\n                        takes_context=True)\ndef paginate(context, page_obj, num_of_pages=5):\n    context['page_obj'] = page_obj\n    context['n_forward'] = num_of_pages + 1\n    context['n_backward'] = -num_of_pages - 1\n    context['next_section'] = (2 * num_of_pages) + 1\n    context['previous_section'] = (-2 * num_of_pages) - 1\n    return context\n\n\n@register.simple_tag\ndef margin_for_variant(stock):\n    return get_margin_for_variant(stock)\n\n\n@register.simple_tag\ndef margins_for_variant(variant):\n    margins = get_variant_costs_data(variant)['margins']\n    return margins\n\n\n@register.inclusion_tag('dashboard/includes/_filters.html', takes_context=True)\ndef add_filters(context, filter_set, sort_by_filter_name='sort_by'):\n    chips = []\n    request_get = context['request'].GET.copy()\n    for filter_name in filter_set.form.cleaned_data.keys():\n        if filter_name == sort_by_filter_name:\n            # Skip processing of sort_by filter, as it's rendered differently\n            continue\n\n        field = filter_set.form[filter_name]\n        if field.value() not in ['', None]:\n            if isinstance(field.field, forms.NullBooleanField):\n                items = handle_nullboolean(field, request_get)\n            elif isinstance(field.field, forms.ModelMultipleChoiceField):\n                items = handle_multiple_model_choice(field, request_get)\n            elif isinstance(field.field, forms.MultipleChoiceField):\n                items = handle_multiple_choice(field, request_get)\n            elif isinstance(field.field, forms.ModelChoiceField):\n                items = handle_single_model_choice(field, request_get)\n            elif isinstance(field.field, forms.ChoiceField):\n                items = handle_single_choice(field, request_get)\n            elif isinstance(field.field, RangeField):\n                items = handle_range(field, request_get)\n            else:\n                items = handle_default(field, request_get)\n            chips.extend(items)\n    return {\n        'chips': chips, 'filter': filter_set, 'count': filter_set.qs.count(),\n        'sort_by': request_get.get(sort_by_filter_name, None)}\n\n\n@register.simple_tag(takes_context=True)\ndef serialize_messages(context):\n    \"\"\"Serialize django.contrib.messages to JSON\"\"\"\n    messages = context.get('messages', [])\n    data = {}\n    for i, message in enumerate(messages):\n        data[i] = str(message)\n    return dumps(data)\n", "path": "saleor/dashboard/templatetags/utils.py"}]}