prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Invalid query parameters cause internal server error
  ```
    File "akvo/rest/filters.py", line 61, in filter_queryset
      queryset = getattr(queryset, param)(**args_or_kwargs)
  ```
  
  In the new API filtering, you get an internal server error when the query is not correct, e.g.: http://rsr.akvo.org/rest/v1/project/?filter={'incorrect':'code'}. 
  
  We should catch this and return the error message in a dict with detail as key. E.g. `{detail: 'Related Field got invalid lookup: incorrect'}`
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `akvo/rest/filters.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 
  3 # Akvo Reporting is covered by the GNU Affero General Public License.
  4 # See more details in the license.txt file located at the root folder of the Akvo RSR module.
  5 # For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
  6 
  7 import ast
  8 
  9 from django.db.models import Q
  10 
  11 from rest_framework import filters
  12 
  13 
  14 class RSRGenericFilterBackend(filters.BaseFilterBackend):
  15 
  16     def filter_queryset(self, request, queryset, view):
  17         """
  18         Return a queryset possibly filtered by query param values.
  19         The filter looks for the query param keys filter and exclude
  20         For each of these query param the value is evaluated using ast.literal_eval() and used as
  21         kwargs in queryset.filter and queryset.exclude respectively.
  22 
  23         Example URLs:
  24             http://rsr.akvo.org/rest/v1/project/?filter={'title__icontains':'water','currency':'EUR'}
  25             http://rsr.akvo.org/rest/v1/project/?filter={'title__icontains':'water'}&exclude={'currency':'EUR'}
  26 
  27         It's also possible to specify models to be included in select_related() and
  28         prefetch_related() calls on the queryset, but specifying these in lists of strings as the
  29         values for the query sting params select_relates and prefetch_related.
  30 
  31         Example:
  32             http://rsr.akvo.org/rest/v1/project/?filter={'partners__in':[42,43]}&prefetch_related=['partners']
  33 
  34         Finally limited support for filtering on multiple arguments using logical OR between
  35         those expressions is available. To use this supply two or more query string keywords on the
  36         form q_filter1, q_filter2... where the value is a dict that can be used as a kwarg in a Q
  37         object. All those Q objects created are used in a queryset.filter() call concatenated using
  38         the | operator.
  39         """
  40         def eval_query_value(request, key):
  41             """
  42             Use ast.literal_eval() to evaluate a query string value as a python data type object
  43             :param request: the django request object
  44             :param param: the query string param key
  45             :return: a python data type object, or None if literal_eval() fails
  46             """
  47             value = request.QUERY_PARAMS.get(key, None)
  48             try:
  49                 return ast.literal_eval(value)
  50             except ValueError:
  51                 return None
  52 
  53         qs_params = ['filter', 'exclude', 'select_related', 'prefetch_related']
  54 
  55         # evaluate each query string param, and apply the queryset method with the same name
  56         for param in qs_params:
  57             args_or_kwargs = eval_query_value(request, param)
  58             if args_or_kwargs:
  59                 # filter and exclude are called with a dict kwarg, the _related methods with a list
  60                 if param in ['filter', 'exclude',]:
  61                     queryset = getattr(queryset, param)(**args_or_kwargs)
  62                 else:
  63                     queryset = getattr(queryset, param)(*args_or_kwargs)
  64 
  65         # support for Q expressions, limited to OR-concatenated filtering
  66         if request.QUERY_PARAMS.get('q_filter1', None):
  67             i = 1
  68             q_queries = []
  69             while request.QUERY_PARAMS.get('q_filter{}'.format(i), None):
  70                 query_arg = eval_query_value(request, 'q_filter{}'.format(i))
  71                 if query_arg:
  72                     q_queries += [query_arg]
  73                 i += 1
  74 
  75             q_expr = Q(**q_queries[0])
  76             for query in q_queries[1:]:
  77                 q_expr = q_expr | Q(**query)
  78 
  79             queryset = queryset.filter(q_expr)
  80 
  81         return queryset
  82
  ```
  --- 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/akvo/rest/filters.py b/akvo/rest/filters.py
  --- a/akvo/rest/filters.py
  +++ b/akvo/rest/filters.py
  @@ -7,8 +7,10 @@
   import ast
   
   from django.db.models import Q
  +from django.core.exceptions import FieldError
   
  -from rest_framework import filters
  +from rest_framework import filters, status
  +from rest_framework.exceptions import APIException
   
   
   class RSRGenericFilterBackend(filters.BaseFilterBackend):
  @@ -57,10 +59,14 @@
               args_or_kwargs = eval_query_value(request, param)
               if args_or_kwargs:
                   # filter and exclude are called with a dict kwarg, the _related methods with a list
  -                if param in ['filter', 'exclude',]:
  -                    queryset = getattr(queryset, param)(**args_or_kwargs)
  -                else:
  -                    queryset = getattr(queryset, param)(*args_or_kwargs)
  +                try:
  +                    if param in ['filter', 'exclude',]:
  +                        queryset = getattr(queryset, param)(**args_or_kwargs)
  +                    else:
  +                        queryset = getattr(queryset, param)(*args_or_kwargs)
  +
  +                except FieldError as e:
  +                    raise APIException("Error in request: {message}".format(message=e.message))
   
           # support for Q expressions, limited to OR-concatenated filtering
           if request.QUERY_PARAMS.get('q_filter1', None):
  
verification_info: {"golden_diff": "diff --git a/akvo/rest/filters.py b/akvo/rest/filters.py\n--- a/akvo/rest/filters.py\n+++ b/akvo/rest/filters.py\n@@ -7,8 +7,10 @@\n import ast\n \n from django.db.models import Q\n+from django.core.exceptions import FieldError\n \n-from rest_framework import filters\n+from rest_framework import filters, status\n+from rest_framework.exceptions import APIException\n \n \n class RSRGenericFilterBackend(filters.BaseFilterBackend):\n@@ -57,10 +59,14 @@\n             args_or_kwargs = eval_query_value(request, param)\n             if args_or_kwargs:\n                 # filter and exclude are called with a dict kwarg, the _related methods with a list\n-                if param in ['filter', 'exclude',]:\n-                    queryset = getattr(queryset, param)(**args_or_kwargs)\n-                else:\n-                    queryset = getattr(queryset, param)(*args_or_kwargs)\n+                try:\n+                    if param in ['filter', 'exclude',]:\n+                        queryset = getattr(queryset, param)(**args_or_kwargs)\n+                    else:\n+                        queryset = getattr(queryset, param)(*args_or_kwargs)\n+\n+                except FieldError as e:\n+                    raise APIException(\"Error in request: {message}\".format(message=e.message))\n \n         # support for Q expressions, limited to OR-concatenated filtering\n         if request.QUERY_PARAMS.get('q_filter1', None):\n", "issue": "Invalid query parameters cause internal server error\n```\n  File \"akvo/rest/filters.py\", line 61, in filter_queryset\n    queryset = getattr(queryset, param)(**args_or_kwargs)\n```\n\nIn the new API filtering, you get an internal server error when the query is not correct, e.g.: http://rsr.akvo.org/rest/v1/project/?filter={'incorrect':'code'}. \n\nWe should catch this and return the error message in a dict with detail as key. E.g. `{detail: 'Related Field got invalid lookup: incorrect'}`\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo Reporting is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\nimport ast\n\nfrom django.db.models import Q\n\nfrom rest_framework import filters\n\n\nclass RSRGenericFilterBackend(filters.BaseFilterBackend):\n\n    def filter_queryset(self, request, queryset, view):\n        \"\"\"\n        Return a queryset possibly filtered by query param values.\n        The filter looks for the query param keys filter and exclude\n        For each of these query param the value is evaluated using ast.literal_eval() and used as\n        kwargs in queryset.filter and queryset.exclude respectively.\n\n        Example URLs:\n            http://rsr.akvo.org/rest/v1/project/?filter={'title__icontains':'water','currency':'EUR'}\n            http://rsr.akvo.org/rest/v1/project/?filter={'title__icontains':'water'}&exclude={'currency':'EUR'}\n\n        It's also possible to specify models to be included in select_related() and\n        prefetch_related() calls on the queryset, but specifying these in lists of strings as the\n        values for the query sting params select_relates and prefetch_related.\n\n        Example:\n            http://rsr.akvo.org/rest/v1/project/?filter={'partners__in':[42,43]}&prefetch_related=['partners']\n\n        Finally limited support for filtering on multiple arguments using logical OR between\n        those expressions is available. To use this supply two or more query string keywords on the\n        form q_filter1, q_filter2... where the value is a dict that can be used as a kwarg in a Q\n        object. All those Q objects created are used in a queryset.filter() call concatenated using\n        the | operator.\n        \"\"\"\n        def eval_query_value(request, key):\n            \"\"\"\n            Use ast.literal_eval() to evaluate a query string value as a python data type object\n            :param request: the django request object\n            :param param: the query string param key\n            :return: a python data type object, or None if literal_eval() fails\n            \"\"\"\n            value = request.QUERY_PARAMS.get(key, None)\n            try:\n                return ast.literal_eval(value)\n            except ValueError:\n                return None\n\n        qs_params = ['filter', 'exclude', 'select_related', 'prefetch_related']\n\n        # evaluate each query string param, and apply the queryset method with the same name\n        for param in qs_params:\n            args_or_kwargs = eval_query_value(request, param)\n            if args_or_kwargs:\n                # filter and exclude are called with a dict kwarg, the _related methods with a list\n                if param in ['filter', 'exclude',]:\n                    queryset = getattr(queryset, param)(**args_or_kwargs)\n                else:\n                    queryset = getattr(queryset, param)(*args_or_kwargs)\n\n        # support for Q expressions, limited to OR-concatenated filtering\n        if request.QUERY_PARAMS.get('q_filter1', None):\n            i = 1\n            q_queries = []\n            while request.QUERY_PARAMS.get('q_filter{}'.format(i), None):\n                query_arg = eval_query_value(request, 'q_filter{}'.format(i))\n                if query_arg:\n                    q_queries += [query_arg]\n                i += 1\n\n            q_expr = Q(**q_queries[0])\n            for query in q_queries[1:]:\n                q_expr = q_expr | Q(**query)\n\n            queryset = queryset.filter(q_expr)\n\n        return queryset\n", "path": "akvo/rest/filters.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo Reporting is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\nimport ast\n\nfrom django.db.models import Q\nfrom django.core.exceptions import FieldError\n\nfrom rest_framework import filters, status\nfrom rest_framework.exceptions import APIException\n\n\nclass RSRGenericFilterBackend(filters.BaseFilterBackend):\n\n    def filter_queryset(self, request, queryset, view):\n        \"\"\"\n        Return a queryset possibly filtered by query param values.\n        The filter looks for the query param keys filter and exclude\n        For each of these query param the value is evaluated using ast.literal_eval() and used as\n        kwargs in queryset.filter and queryset.exclude respectively.\n\n        Example URLs:\n            http://rsr.akvo.org/rest/v1/project/?filter={'title__icontains':'water','currency':'EUR'}\n            http://rsr.akvo.org/rest/v1/project/?filter={'title__icontains':'water'}&exclude={'currency':'EUR'}\n\n        It's also possible to specify models to be included in select_related() and\n        prefetch_related() calls on the queryset, but specifying these in lists of strings as the\n        values for the query sting params select_relates and prefetch_related.\n\n        Example:\n            http://rsr.akvo.org/rest/v1/project/?filter={'partners__in':[42,43]}&prefetch_related=['partners']\n\n        Finally limited support for filtering on multiple arguments using logical OR between\n        those expressions is available. To use this supply two or more query string keywords on the\n        form q_filter1, q_filter2... where the value is a dict that can be used as a kwarg in a Q\n        object. All those Q objects created are used in a queryset.filter() call concatenated using\n        the | operator.\n        \"\"\"\n        def eval_query_value(request, key):\n            \"\"\"\n            Use ast.literal_eval() to evaluate a query string value as a python data type object\n            :param request: the django request object\n            :param param: the query string param key\n            :return: a python data type object, or None if literal_eval() fails\n            \"\"\"\n            value = request.QUERY_PARAMS.get(key, None)\n            try:\n                return ast.literal_eval(value)\n            except ValueError:\n                return None\n\n        qs_params = ['filter', 'exclude', 'select_related', 'prefetch_related']\n\n        # evaluate each query string param, and apply the queryset method with the same name\n        for param in qs_params:\n            args_or_kwargs = eval_query_value(request, param)\n            if args_or_kwargs:\n                # filter and exclude are called with a dict kwarg, the _related methods with a list\n                try:\n                    if param in ['filter', 'exclude',]:\n                        queryset = getattr(queryset, param)(**args_or_kwargs)\n                    else:\n                        queryset = getattr(queryset, param)(*args_or_kwargs)\n\n                except FieldError as e:\n                    raise APIException(\"Error in request: {message}\".format(message=e.message))\n\n        # support for Q expressions, limited to OR-concatenated filtering\n        if request.QUERY_PARAMS.get('q_filter1', None):\n            i = 1\n            q_queries = []\n            while request.QUERY_PARAMS.get('q_filter{}'.format(i), None):\n                query_arg = eval_query_value(request, 'q_filter{}'.format(i))\n                if query_arg:\n                    q_queries += [query_arg]\n                i += 1\n\n            q_expr = Q(**q_queries[0])\n            for query in q_queries[1:]:\n                q_expr = q_expr | Q(**query)\n\n            queryset = queryset.filter(q_expr)\n\n        return queryset\n", "path": "akvo/rest/filters.py"}]}