We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
/search/parameter_field_list/ failures with Unicode first/last names in Users table
This can occur:
```
Internal Server Error: /search/parameter_field_list/
Traceback (most recent call last):
  File "/home/mytardis/virtualenvs/mytardis/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/mytardis/mytardis/tardis/search/views.py", line 282, in retrieve_field_list
    fieldList = '+'.join([str(fn) for fn in auto_list])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 8: ordinal not in range(128)
```

if there's a user with a non-ASCII character in their first or last name.  The relevant code in tardis/search/views.py is:

```
usernames = [u.first_name + ' ' + u.last_name + ':username' for u in users]
...
auto_list = usernames + searchableFields
fieldList = '+'.join([str(fn) for fn in auto_list])
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tardis/search/views.py`
Content:
```
1 """
2 views relevant to search
3 """
4 import logging
5 import warnings
6 
7 from django.contrib.auth.models import User
8 from django.http import HttpResponse
9 from haystack.generic_views import SearchView
10 
11 from tardis.search.forms import GroupedSearchForm
12 from tardis.search.utils import SearchQueryString
13 from tardis.tardis_portal.auth import decorators as authz
14 from tardis.tardis_portal.deprecations import RemovedInMyTardis311Warning
15 from tardis.tardis_portal.forms import createSearchDatafileSelectionForm
16 from tardis.tardis_portal.hacks import oracle_dbops_hack
17 from tardis.tardis_portal.models import Experiment
18 from tardis.tardis_portal.shortcuts import render_response_search, \
19     render_response_index
20 from tardis.tardis_portal.views.utils import __forwardToSearchExperimentFormPage, \
21     __getSearchExperimentForm, __processExperimentParameters, \
22     __getSearchDatafileForm, __processDatafileParameters, \
23     __forwardToSearchDatafileFormPage
24 
25 logger = logging.getLogger(__name__)
26 
27 
28 def getNewSearchDatafileSelectionForm(initial=None):
29     DatafileSelectionForm = createSearchDatafileSelectionForm(initial)
30     return DatafileSelectionForm()
31 
32 
33 @oracle_dbops_hack
34 def search_experiment(request):
35 
36     """Either show the search experiment form or the result of the search
37     experiment query.
38 
39     """
40 
41     if not request.GET:
42         return __forwardToSearchExperimentFormPage(request)
43 
44     form = __getSearchExperimentForm(request)
45     experiments = __processExperimentParameters(request, form)
46 
47     # check if the submitted form is valid
48     if experiments is not None:
49         bodyclass = 'list'
50     else:
51         return __forwardToSearchExperimentFormPage(request)
52 
53     # remove information from previous searches from session
54     if 'datafileResults' in request.session:
55         del request.session['datafileResults']
56 
57     results = []
58     for e in experiments:
59         result = {}
60         result['sr'] = e
61         result['dataset_hit'] = False
62         result['datafile_hit'] = False
63         result['experiment_hit'] = True
64         results.append(result)
65     c = {'header': 'Search Experiment',
66          'experiments': results,
67          'bodyclass': bodyclass}
68     url = 'tardis_portal/search_experiment_results.html'
69     return HttpResponse(render_response_search(request, url, c))
70 
71 
72 def search_quick(request):
73     get = False
74     experiments = Experiment.objects.all().order_by('title')
75 
76     if 'results' in request.GET:
77         get = True
78         if 'quicksearch' in request.GET and request.GET['quicksearch']:
79             experiments = \
80                 experiments.filter(
81                     title__icontains=request.GET['quicksearch']) | \
82                 experiments.filter(
83                     institution_name__icontains=request.GET['quicksearch']) | \
84                 experiments.filter(
85                     experimentauthor__author__name__icontains=request.GET[
86                         'quicksearch']) | \
87                 experiments.filter(
88                     pdbid__pdbid__icontains=request.GET['quicksearch'])
89 
90             experiments = experiments.distinct()
91 
92             logger.debug(experiments)
93 
94     c = {'submitted': get, 'experiments': experiments,
95          'subtitle': 'Search Experiments'}
96     return HttpResponse(render_response_index(request,
97                         'tardis_portal/search_experiment.html', c))
98 
99 
100 def search_datafile(request):  # too complex # noqa
101     """Either show the search datafile form or the result of the search
102     datafile query.
103 
104     """
105     warnings.warn(
106         "The old DataFile search form (triggered by the /search/datafile/ "
107         "URL) was only useful for X-Ray Diffraction data.  It needs to be "
108         "rewritten if it is to be useful for other data types.",
109         RemovedInMyTardis311Warning
110     )
111     if 'type' in request.GET:
112         searchQueryType = request.GET.get('type')
113     else:
114         # for now we'll default to MX if nothing is provided
115         # TODO: should we forward the page to experiment search page if
116         #       nothing is provided in the future?
117         searchQueryType = 'mx'
118     logger.info('search_datafile: searchQueryType {0}'.format(searchQueryType))
119     # TODO: check if going to /search/datafile will flag an error in unit test
120     bodyclass = None
121 
122     if 'page' not in request.GET and 'type' in request.GET and \
123             len(request.GET) > 1:
124         # display the 1st page of the results
125 
126         form = __getSearchDatafileForm(request, searchQueryType)
127         datafile_results = __processDatafileParameters(
128             request, searchQueryType, form)
129         if datafile_results is not None:
130             bodyclass = 'list'
131         else:
132             return __forwardToSearchDatafileFormPage(
133                 request, searchQueryType, form)
134 
135     else:
136         if 'page' in request.GET:
137             # succeeding pages of pagination
138             if 'datafileResults' in request.session:
139                 datafile_results = request.session['datafileResults']
140             else:
141                 form = __getSearchDatafileForm(request, searchQueryType)
142                 datafile_results = __processDatafileParameters(
143                     request, searchQueryType, form)
144                 if datafile_results is not None:
145                     bodyclass = 'list'
146                 else:
147                     return __forwardToSearchDatafileFormPage(
148                         request, searchQueryType, form)
149         else:
150             # display the form
151             if 'datafileResults' in request.session:
152                 del request.session['datafileResults']
153             return __forwardToSearchDatafileFormPage(request, searchQueryType)
154 
155     # process the files to be displayed by the paginator...
156     # paginator = Paginator(datafile_results,
157     #                      constants.DATAFILE_RESULTS_PER_PAGE)
158 
159     # try:
160     #    page = int(request.GET.get('page', '1'))
161     # except ValueError:
162     #    page = 1
163 
164     # If page request (9999) is out of :range, deliver last page of results.
165     # try:
166     #    datafiles = paginator.page(page)
167     # except (EmptyPage, InvalidPage):
168     #    datafiles = paginator.page(paginator.num_pages)
169 
170     import re
171     cleanedUpQueryString = re.sub('&page=\d+', '',
172                                   request.META['QUERY_STRING'])
173 
174     # get experiments associated with datafiles
175     if datafile_results:
176         experiment_pks = list(set(datafile_results.values_list(
177             'dataset__experiments', flat=True)))
178         experiments = Experiment.safe.in_bulk(experiment_pks)
179     else:
180         experiments = {}
181 
182     results = []
183     for key, e in experiments.items():
184         result = {}
185         result['sr'] = e
186         result['dataset_hit'] = False
187         result['datafile_hit'] = True
188         result['experiment_hit'] = False
189         results.append(result)
190 
191     c = {
192         'experiments': results,
193         'datafiles': datafile_results,
194         # 'paginator': paginator,
195         'query_string': cleanedUpQueryString,
196         'subtitle': 'Search Datafiles',
197         'nav': [{'name': 'Search Datafile', 'link': '/search/datafile/'}],
198         'bodyclass': bodyclass,
199         'search_pressed': True,
200         'searchDatafileSelectionForm': getNewSearchDatafileSelectionForm()}
201     url = 'tardis_portal/search_experiment_results.html'
202     return HttpResponse(render_response_search(request, url, c))
203 
204 
205 class ExperimentSearchView(SearchView):
206     def __name__(self):
207         return "ExperimentSearchView"
208 
209     def extra_context(self):
210         extra = super(ExperimentSearchView, self).extra_context()
211         # Results may contain Experiments, Datasets and DataFiles.
212         # Group them into experiments, noting whether or not the search
213         # hits were in the Dataset(s) or DataFile(s)
214         results = self.results
215         facets = results.facet_counts()
216         if facets:
217             experiment_facets = facets['fields']['experiment_id_stored']
218             experiment_ids = [int(f[0])
219                               for f in experiment_facets if int(f[1]) > 0]
220         else:
221             experiment_ids = []
222 
223         access_list = []
224 
225         if self.request.user.is_authenticated():
226             access_list.extend(
227                 [e.pk for e in
228                  authz.get_accessible_experiments(self.request)])
229 
230         access_list.extend(
231             [e.pk for e in Experiment.objects
232                 .exclude(public_access=Experiment.PUBLIC_ACCESS_NONE)
233                 .exclude(public_access=Experiment.PUBLIC_ACCESS_EMBARGO)])
234 
235         ids = list(set(experiment_ids) & set(access_list))
236         experiments = Experiment.objects.filter(pk__in=ids)\
237                                         .order_by('-update_time')
238 
239         results = []
240         for e in experiments:
241             result = {'sr': e, 'dataset_hit': False, 'datafile_hit': False,
242                       'experiment_hit': False}
243             results.append(result)
244 
245         extra['experiments'] = results
246         return extra
247 
248     # override SearchView's method in order to
249     # return a ResponseContext
250     def create_response(self):
251         (paginator, page) = self.build_page()
252 
253         # Remove unnecessary whitespace
254         # TODO this should just be done in the form clean...
255         query = SearchQueryString(self.query)
256         context = {
257             'search_query': query,
258             'form': self.form,
259             'page': page,
260             'paginator': paginator,
261         }
262         context.update(self.extra_context())
263 
264         return render_response_index(self.request, self.template, context)
265 
266 
267 def retrieve_field_list(request):
268 
269     from tardis.search.search_indexes import DataFileIndex
270 
271     # Get all of the fields in the indexes
272     #
273     # TODO: these should be onl read from registered indexes
274     #
275     allFields = DataFileIndex.fields.items()
276 
277     users = User.objects.all()
278 
279     usernames = [u.first_name + ' ' + u.last_name + ':username' for u in users]
280 
281     # Collect all of the indexed (searchable) fields, except
282     # for the main search document ('text')
283     searchableFields = ([key + ':search_field' for key, f in allFields
284                          if f.indexed is True and key != 'text'])
285 
286     auto_list = usernames + searchableFields
287 
288     fieldList = '+'.join([str(fn) for fn in auto_list])
289     return HttpResponse(fieldList)
290 
291 
292 class SingleSearchView(SearchView):
293     form_class = GroupedSearchForm
294     template_name = 'search/search.html'
295 
296     def form_valid(self, form):
297         sqs = form.search(user=self.request.user)
298         context = self.get_context_data(**{
299             self.form_name: form,
300             'query': form.cleaned_data.get(self.search_field),
301             'object_list': sqs,
302         })
303         return self.render_to_response(context)
304
```
--- 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/tardis/search/views.py b/tardis/search/views.py
--- a/tardis/search/views.py
+++ b/tardis/search/views.py
@@ -276,7 +276,11 @@
 
     users = User.objects.all()
 
-    usernames = [u.first_name + ' ' + u.last_name + ':username' for u in users]
+    usernames = [
+        u.first_name.encode('utf-8') +
+        ' ' +
+        u.last_name.encode('utf-8') +
+        ':username' for u in users]
 
     # Collect all of the indexed (searchable) fields, except
     # for the main search document ('text')

{"golden_diff": "diff --git a/tardis/search/views.py b/tardis/search/views.py\n--- a/tardis/search/views.py\n+++ b/tardis/search/views.py\n@@ -276,7 +276,11 @@\n \n     users = User.objects.all()\n \n-    usernames = [u.first_name + ' ' + u.last_name + ':username' for u in users]\n+    usernames = [\n+        u.first_name.encode('utf-8') +\n+        ' ' +\n+        u.last_name.encode('utf-8') +\n+        ':username' for u in users]\n \n     # Collect all of the indexed (searchable) fields, except\n     # for the main search document ('text')\n", "issue": "/search/parameter_field_list/ failures with Unicode first/last names in Users table\nThis can occur:\r\n```\r\nInternal Server Error: /search/parameter_field_list/\r\nTraceback (most recent call last):\r\n  File \"/home/mytardis/virtualenvs/mytardis/local/lib/python2.7/site-packages/django/core/handlers/base.py\", line 132, in get_response\r\n    response = wrapped_callback(request, *callback_args, **callback_kwargs)\r\n  File \"/home/mytardis/mytardis/tardis/search/views.py\", line 282, in retrieve_field_list\r\n    fieldList = '+'.join([str(fn) for fn in auto_list])\r\nUnicodeEncodeError: 'ascii' codec can't encode character u'\\xfc' in position 8: ordinal not in range(128)\r\n```\r\n\r\nif there's a user with a non-ASCII character in their first or last name.  The relevant code in tardis/search/views.py is:\r\n\r\n```\r\nusernames = [u.first_name + ' ' + u.last_name + ':username' for u in users]\r\n...\r\nauto_list = usernames + searchableFields\r\nfieldList = '+'.join([str(fn) for fn in auto_list])\r\n```\r\n\n", "before_files": [{"content": "\"\"\"\nviews relevant to search\n\"\"\"\nimport logging\nimport warnings\n\nfrom django.contrib.auth.models import User\nfrom django.http import HttpResponse\nfrom haystack.generic_views import SearchView\n\nfrom tardis.search.forms import GroupedSearchForm\nfrom tardis.search.utils import SearchQueryString\nfrom tardis.tardis_portal.auth import decorators as authz\nfrom tardis.tardis_portal.deprecations import RemovedInMyTardis311Warning\nfrom tardis.tardis_portal.forms import createSearchDatafileSelectionForm\nfrom tardis.tardis_portal.hacks import oracle_dbops_hack\nfrom tardis.tardis_portal.models import Experiment\nfrom tardis.tardis_portal.shortcuts import render_response_search, \\\n    render_response_index\nfrom tardis.tardis_portal.views.utils import __forwardToSearchExperimentFormPage, \\\n    __getSearchExperimentForm, __processExperimentParameters, \\\n    __getSearchDatafileForm, __processDatafileParameters, \\\n    __forwardToSearchDatafileFormPage\n\nlogger = logging.getLogger(__name__)\n\n\ndef getNewSearchDatafileSelectionForm(initial=None):\n    DatafileSelectionForm = createSearchDatafileSelectionForm(initial)\n    return DatafileSelectionForm()\n\n\n@oracle_dbops_hack\ndef search_experiment(request):\n\n    \"\"\"Either show the search experiment form or the result of the search\n    experiment query.\n\n    \"\"\"\n\n    if not request.GET:\n        return __forwardToSearchExperimentFormPage(request)\n\n    form = __getSearchExperimentForm(request)\n    experiments = __processExperimentParameters(request, form)\n\n    # check if the submitted form is valid\n    if experiments is not None:\n        bodyclass = 'list'\n    else:\n        return __forwardToSearchExperimentFormPage(request)\n\n    # remove information from previous searches from session\n    if 'datafileResults' in request.session:\n        del request.session['datafileResults']\n\n    results = []\n    for e in experiments:\n        result = {}\n        result['sr'] = e\n        result['dataset_hit'] = False\n        result['datafile_hit'] = False\n        result['experiment_hit'] = True\n        results.append(result)\n    c = {'header': 'Search Experiment',\n         'experiments': results,\n         'bodyclass': bodyclass}\n    url = 'tardis_portal/search_experiment_results.html'\n    return HttpResponse(render_response_search(request, url, c))\n\n\ndef search_quick(request):\n    get = False\n    experiments = Experiment.objects.all().order_by('title')\n\n    if 'results' in request.GET:\n        get = True\n        if 'quicksearch' in request.GET and request.GET['quicksearch']:\n            experiments = \\\n                experiments.filter(\n                    title__icontains=request.GET['quicksearch']) | \\\n                experiments.filter(\n                    institution_name__icontains=request.GET['quicksearch']) | \\\n                experiments.filter(\n                    experimentauthor__author__name__icontains=request.GET[\n                        'quicksearch']) | \\\n                experiments.filter(\n                    pdbid__pdbid__icontains=request.GET['quicksearch'])\n\n            experiments = experiments.distinct()\n\n            logger.debug(experiments)\n\n    c = {'submitted': get, 'experiments': experiments,\n         'subtitle': 'Search Experiments'}\n    return HttpResponse(render_response_index(request,\n                        'tardis_portal/search_experiment.html', c))\n\n\ndef search_datafile(request):  # too complex # noqa\n    \"\"\"Either show the search datafile form or the result of the search\n    datafile query.\n\n    \"\"\"\n    warnings.warn(\n        \"The old DataFile search form (triggered by the /search/datafile/ \"\n        \"URL) was only useful for X-Ray Diffraction data.  It needs to be \"\n        \"rewritten if it is to be useful for other data types.\",\n        RemovedInMyTardis311Warning\n    )\n    if 'type' in request.GET:\n        searchQueryType = request.GET.get('type')\n    else:\n        # for now we'll default to MX if nothing is provided\n        # TODO: should we forward the page to experiment search page if\n        #       nothing is provided in the future?\n        searchQueryType = 'mx'\n    logger.info('search_datafile: searchQueryType {0}'.format(searchQueryType))\n    # TODO: check if going to /search/datafile will flag an error in unit test\n    bodyclass = None\n\n    if 'page' not in request.GET and 'type' in request.GET and \\\n            len(request.GET) > 1:\n        # display the 1st page of the results\n\n        form = __getSearchDatafileForm(request, searchQueryType)\n        datafile_results = __processDatafileParameters(\n            request, searchQueryType, form)\n        if datafile_results is not None:\n            bodyclass = 'list'\n        else:\n            return __forwardToSearchDatafileFormPage(\n                request, searchQueryType, form)\n\n    else:\n        if 'page' in request.GET:\n            # succeeding pages of pagination\n            if 'datafileResults' in request.session:\n                datafile_results = request.session['datafileResults']\n            else:\n                form = __getSearchDatafileForm(request, searchQueryType)\n                datafile_results = __processDatafileParameters(\n                    request, searchQueryType, form)\n                if datafile_results is not None:\n                    bodyclass = 'list'\n                else:\n                    return __forwardToSearchDatafileFormPage(\n                        request, searchQueryType, form)\n        else:\n            # display the form\n            if 'datafileResults' in request.session:\n                del request.session['datafileResults']\n            return __forwardToSearchDatafileFormPage(request, searchQueryType)\n\n    # process the files to be displayed by the paginator...\n    # paginator = Paginator(datafile_results,\n    #                      constants.DATAFILE_RESULTS_PER_PAGE)\n\n    # try:\n    #    page = int(request.GET.get('page', '1'))\n    # except ValueError:\n    #    page = 1\n\n    # If page request (9999) is out of :range, deliver last page of results.\n    # try:\n    #    datafiles = paginator.page(page)\n    # except (EmptyPage, InvalidPage):\n    #    datafiles = paginator.page(paginator.num_pages)\n\n    import re\n    cleanedUpQueryString = re.sub('&page=\\d+', '',\n                                  request.META['QUERY_STRING'])\n\n    # get experiments associated with datafiles\n    if datafile_results:\n        experiment_pks = list(set(datafile_results.values_list(\n            'dataset__experiments', flat=True)))\n        experiments = Experiment.safe.in_bulk(experiment_pks)\n    else:\n        experiments = {}\n\n    results = []\n    for key, e in experiments.items():\n        result = {}\n        result['sr'] = e\n        result['dataset_hit'] = False\n        result['datafile_hit'] = True\n        result['experiment_hit'] = False\n        results.append(result)\n\n    c = {\n        'experiments': results,\n        'datafiles': datafile_results,\n        # 'paginator': paginator,\n        'query_string': cleanedUpQueryString,\n        'subtitle': 'Search Datafiles',\n        'nav': [{'name': 'Search Datafile', 'link': '/search/datafile/'}],\n        'bodyclass': bodyclass,\n        'search_pressed': True,\n        'searchDatafileSelectionForm': getNewSearchDatafileSelectionForm()}\n    url = 'tardis_portal/search_experiment_results.html'\n    return HttpResponse(render_response_search(request, url, c))\n\n\nclass ExperimentSearchView(SearchView):\n    def __name__(self):\n        return \"ExperimentSearchView\"\n\n    def extra_context(self):\n        extra = super(ExperimentSearchView, self).extra_context()\n        # Results may contain Experiments, Datasets and DataFiles.\n        # Group them into experiments, noting whether or not the search\n        # hits were in the Dataset(s) or DataFile(s)\n        results = self.results\n        facets = results.facet_counts()\n        if facets:\n            experiment_facets = facets['fields']['experiment_id_stored']\n            experiment_ids = [int(f[0])\n                              for f in experiment_facets if int(f[1]) > 0]\n        else:\n            experiment_ids = []\n\n        access_list = []\n\n        if self.request.user.is_authenticated():\n            access_list.extend(\n                [e.pk for e in\n                 authz.get_accessible_experiments(self.request)])\n\n        access_list.extend(\n            [e.pk for e in Experiment.objects\n                .exclude(public_access=Experiment.PUBLIC_ACCESS_NONE)\n                .exclude(public_access=Experiment.PUBLIC_ACCESS_EMBARGO)])\n\n        ids = list(set(experiment_ids) & set(access_list))\n        experiments = Experiment.objects.filter(pk__in=ids)\\\n                                        .order_by('-update_time')\n\n        results = []\n        for e in experiments:\n            result = {'sr': e, 'dataset_hit': False, 'datafile_hit': False,\n                      'experiment_hit': False}\n            results.append(result)\n\n        extra['experiments'] = results\n        return extra\n\n    # override SearchView's method in order to\n    # return a ResponseContext\n    def create_response(self):\n        (paginator, page) = self.build_page()\n\n        # Remove unnecessary whitespace\n        # TODO this should just be done in the form clean...\n        query = SearchQueryString(self.query)\n        context = {\n            'search_query': query,\n            'form': self.form,\n            'page': page,\n            'paginator': paginator,\n        }\n        context.update(self.extra_context())\n\n        return render_response_index(self.request, self.template, context)\n\n\ndef retrieve_field_list(request):\n\n    from tardis.search.search_indexes import DataFileIndex\n\n    # Get all of the fields in the indexes\n    #\n    # TODO: these should be onl read from registered indexes\n    #\n    allFields = DataFileIndex.fields.items()\n\n    users = User.objects.all()\n\n    usernames = [u.first_name + ' ' + u.last_name + ':username' for u in users]\n\n    # Collect all of the indexed (searchable) fields, except\n    # for the main search document ('text')\n    searchableFields = ([key + ':search_field' for key, f in allFields\n                         if f.indexed is True and key != 'text'])\n\n    auto_list = usernames + searchableFields\n\n    fieldList = '+'.join([str(fn) for fn in auto_list])\n    return HttpResponse(fieldList)\n\n\nclass SingleSearchView(SearchView):\n    form_class = GroupedSearchForm\n    template_name = 'search/search.html'\n\n    def form_valid(self, form):\n        sqs = form.search(user=self.request.user)\n        context = self.get_context_data(**{\n            self.form_name: form,\n            'query': form.cleaned_data.get(self.search_field),\n            'object_list': sqs,\n        })\n        return self.render_to_response(context)\n", "path": "tardis/search/views.py"}], "after_files": [{"content": "\"\"\"\nviews relevant to search\n\"\"\"\nimport logging\nimport warnings\n\nfrom django.contrib.auth.models import User\nfrom django.http import HttpResponse\nfrom haystack.generic_views import SearchView\n\nfrom tardis.search.forms import GroupedSearchForm\nfrom tardis.search.utils import SearchQueryString\nfrom tardis.tardis_portal.auth import decorators as authz\nfrom tardis.tardis_portal.deprecations import RemovedInMyTardis311Warning\nfrom tardis.tardis_portal.forms import createSearchDatafileSelectionForm\nfrom tardis.tardis_portal.hacks import oracle_dbops_hack\nfrom tardis.tardis_portal.models import Experiment\nfrom tardis.tardis_portal.shortcuts import render_response_search, \\\n    render_response_index\nfrom tardis.tardis_portal.views.utils import __forwardToSearchExperimentFormPage, \\\n    __getSearchExperimentForm, __processExperimentParameters, \\\n    __getSearchDatafileForm, __processDatafileParameters, \\\n    __forwardToSearchDatafileFormPage\n\nlogger = logging.getLogger(__name__)\n\n\ndef getNewSearchDatafileSelectionForm(initial=None):\n    DatafileSelectionForm = createSearchDatafileSelectionForm(initial)\n    return DatafileSelectionForm()\n\n\n@oracle_dbops_hack\ndef search_experiment(request):\n\n    \"\"\"Either show the search experiment form or the result of the search\n    experiment query.\n\n    \"\"\"\n\n    if not request.GET:\n        return __forwardToSearchExperimentFormPage(request)\n\n    form = __getSearchExperimentForm(request)\n    experiments = __processExperimentParameters(request, form)\n\n    # check if the submitted form is valid\n    if experiments is not None:\n        bodyclass = 'list'\n    else:\n        return __forwardToSearchExperimentFormPage(request)\n\n    # remove information from previous searches from session\n    if 'datafileResults' in request.session:\n        del request.session['datafileResults']\n\n    results = []\n    for e in experiments:\n        result = {}\n        result['sr'] = e\n        result['dataset_hit'] = False\n        result['datafile_hit'] = False\n        result['experiment_hit'] = True\n        results.append(result)\n    c = {'header': 'Search Experiment',\n         'experiments': results,\n         'bodyclass': bodyclass}\n    url = 'tardis_portal/search_experiment_results.html'\n    return HttpResponse(render_response_search(request, url, c))\n\n\ndef search_quick(request):\n    get = False\n    experiments = Experiment.objects.all().order_by('title')\n\n    if 'results' in request.GET:\n        get = True\n        if 'quicksearch' in request.GET and request.GET['quicksearch']:\n            experiments = \\\n                experiments.filter(\n                    title__icontains=request.GET['quicksearch']) | \\\n                experiments.filter(\n                    institution_name__icontains=request.GET['quicksearch']) | \\\n                experiments.filter(\n                    experimentauthor__author__name__icontains=request.GET[\n                        'quicksearch']) | \\\n                experiments.filter(\n                    pdbid__pdbid__icontains=request.GET['quicksearch'])\n\n            experiments = experiments.distinct()\n\n            logger.debug(experiments)\n\n    c = {'submitted': get, 'experiments': experiments,\n         'subtitle': 'Search Experiments'}\n    return HttpResponse(render_response_index(request,\n                        'tardis_portal/search_experiment.html', c))\n\n\ndef search_datafile(request):  # too complex # noqa\n    \"\"\"Either show the search datafile form or the result of the search\n    datafile query.\n\n    \"\"\"\n    warnings.warn(\n        \"The old DataFile search form (triggered by the /search/datafile/ \"\n        \"URL) was only useful for X-Ray Diffraction data.  It needs to be \"\n        \"rewritten if it is to be useful for other data types.\",\n        RemovedInMyTardis311Warning\n    )\n    if 'type' in request.GET:\n        searchQueryType = request.GET.get('type')\n    else:\n        # for now we'll default to MX if nothing is provided\n        # TODO: should we forward the page to experiment search page if\n        #       nothing is provided in the future?\n        searchQueryType = 'mx'\n    logger.info('search_datafile: searchQueryType {0}'.format(searchQueryType))\n    # TODO: check if going to /search/datafile will flag an error in unit test\n    bodyclass = None\n\n    if 'page' not in request.GET and 'type' in request.GET and \\\n            len(request.GET) > 1:\n        # display the 1st page of the results\n\n        form = __getSearchDatafileForm(request, searchQueryType)\n        datafile_results = __processDatafileParameters(\n            request, searchQueryType, form)\n        if datafile_results is not None:\n            bodyclass = 'list'\n        else:\n            return __forwardToSearchDatafileFormPage(\n                request, searchQueryType, form)\n\n    else:\n        if 'page' in request.GET:\n            # succeeding pages of pagination\n            if 'datafileResults' in request.session:\n                datafile_results = request.session['datafileResults']\n            else:\n                form = __getSearchDatafileForm(request, searchQueryType)\n                datafile_results = __processDatafileParameters(\n                    request, searchQueryType, form)\n                if datafile_results is not None:\n                    bodyclass = 'list'\n                else:\n                    return __forwardToSearchDatafileFormPage(\n                        request, searchQueryType, form)\n        else:\n            # display the form\n            if 'datafileResults' in request.session:\n                del request.session['datafileResults']\n            return __forwardToSearchDatafileFormPage(request, searchQueryType)\n\n    # process the files to be displayed by the paginator...\n    # paginator = Paginator(datafile_results,\n    #                      constants.DATAFILE_RESULTS_PER_PAGE)\n\n    # try:\n    #    page = int(request.GET.get('page', '1'))\n    # except ValueError:\n    #    page = 1\n\n    # If page request (9999) is out of :range, deliver last page of results.\n    # try:\n    #    datafiles = paginator.page(page)\n    # except (EmptyPage, InvalidPage):\n    #    datafiles = paginator.page(paginator.num_pages)\n\n    import re\n    cleanedUpQueryString = re.sub('&page=\\d+', '',\n                                  request.META['QUERY_STRING'])\n\n    # get experiments associated with datafiles\n    if datafile_results:\n        experiment_pks = list(set(datafile_results.values_list(\n            'dataset__experiments', flat=True)))\n        experiments = Experiment.safe.in_bulk(experiment_pks)\n    else:\n        experiments = {}\n\n    results = []\n    for key, e in experiments.items():\n        result = {}\n        result['sr'] = e\n        result['dataset_hit'] = False\n        result['datafile_hit'] = True\n        result['experiment_hit'] = False\n        results.append(result)\n\n    c = {\n        'experiments': results,\n        'datafiles': datafile_results,\n        # 'paginator': paginator,\n        'query_string': cleanedUpQueryString,\n        'subtitle': 'Search Datafiles',\n        'nav': [{'name': 'Search Datafile', 'link': '/search/datafile/'}],\n        'bodyclass': bodyclass,\n        'search_pressed': True,\n        'searchDatafileSelectionForm': getNewSearchDatafileSelectionForm()}\n    url = 'tardis_portal/search_experiment_results.html'\n    return HttpResponse(render_response_search(request, url, c))\n\n\nclass ExperimentSearchView(SearchView):\n    def __name__(self):\n        return \"ExperimentSearchView\"\n\n    def extra_context(self):\n        extra = super(ExperimentSearchView, self).extra_context()\n        # Results may contain Experiments, Datasets and DataFiles.\n        # Group them into experiments, noting whether or not the search\n        # hits were in the Dataset(s) or DataFile(s)\n        results = self.results\n        facets = results.facet_counts()\n        if facets:\n            experiment_facets = facets['fields']['experiment_id_stored']\n            experiment_ids = [int(f[0])\n                              for f in experiment_facets if int(f[1]) > 0]\n        else:\n            experiment_ids = []\n\n        access_list = []\n\n        if self.request.user.is_authenticated():\n            access_list.extend(\n                [e.pk for e in\n                 authz.get_accessible_experiments(self.request)])\n\n        access_list.extend(\n            [e.pk for e in Experiment.objects\n                .exclude(public_access=Experiment.PUBLIC_ACCESS_NONE)\n                .exclude(public_access=Experiment.PUBLIC_ACCESS_EMBARGO)])\n\n        ids = list(set(experiment_ids) & set(access_list))\n        experiments = Experiment.objects.filter(pk__in=ids)\\\n                                        .order_by('-update_time')\n\n        results = []\n        for e in experiments:\n            result = {'sr': e, 'dataset_hit': False, 'datafile_hit': False,\n                      'experiment_hit': False}\n            results.append(result)\n\n        extra['experiments'] = results\n        return extra\n\n    # override SearchView's method in order to\n    # return a ResponseContext\n    def create_response(self):\n        (paginator, page) = self.build_page()\n\n        # Remove unnecessary whitespace\n        # TODO this should just be done in the form clean...\n        query = SearchQueryString(self.query)\n        context = {\n            'search_query': query,\n            'form': self.form,\n            'page': page,\n            'paginator': paginator,\n        }\n        context.update(self.extra_context())\n\n        return render_response_index(self.request, self.template, context)\n\n\ndef retrieve_field_list(request):\n\n    from tardis.search.search_indexes import DataFileIndex\n\n    # Get all of the fields in the indexes\n    #\n    # TODO: these should be onl read from registered indexes\n    #\n    allFields = DataFileIndex.fields.items()\n\n    users = User.objects.all()\n\n    usernames = [\n        u.first_name.encode('utf-8') +\n        ' ' +\n        u.last_name.encode('utf-8') +\n        ':username' for u in users]\n\n    # Collect all of the indexed (searchable) fields, except\n    # for the main search document ('text')\n    searchableFields = ([key + ':search_field' for key, f in allFields\n                         if f.indexed is True and key != 'text'])\n\n    auto_list = usernames + searchableFields\n\n    fieldList = '+'.join([str(fn) for fn in auto_list])\n    return HttpResponse(fieldList)\n\n\nclass SingleSearchView(SearchView):\n    form_class = GroupedSearchForm\n    template_name = 'search/search.html'\n\n    def form_valid(self, form):\n        sqs = form.search(user=self.request.user)\n        context = self.get_context_data(**{\n            self.form_name: form,\n            'query': form.cleaned_data.get(self.search_field),\n            'object_list': sqs,\n        })\n        return self.render_to_response(context)\n", "path": "tardis/search/views.py"}]}