We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Use XHR for user select2 widgets
on a site with a lot of users the admin widgets are very slow and unnecessarily push a full list of users


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pootle/apps/pootle_app/views/admin/permissions.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) Pootle contributors.
4 #
5 # This file is a part of the Pootle project. It is distributed under the GPL3
6 # or later license. See the LICENSE file for a copy of the license and the
7 # AUTHORS file for copyright and authorship information.
8 
9 from django import forms
10 from django.contrib.auth import get_user_model
11 
12 from pootle.core.decorators import get_object_or_404
13 from pootle.core.exceptions import Http400
14 from pootle.core.views.admin import PootleAdminFormView
15 from pootle.core.views.mixins import PootleJSONMixin
16 from pootle.i18n.gettext import ugettext as _
17 from pootle_app.forms import PermissionsUsersSearchForm
18 from pootle_app.models import Directory
19 from pootle_app.models.permissions import (PermissionSet,
20                                            get_permission_contenttype)
21 from pootle_app.views.admin import util
22 from pootle_misc.forms import GroupedModelChoiceField
23 
24 
25 User = get_user_model()
26 
27 PERMISSIONS = {
28     'positive': ['view', 'suggest', 'translate', 'review', 'administrate'],
29     'negative': ['hide'],
30 }
31 
32 
33 class PermissionFormField(forms.ModelMultipleChoiceField):
34 
35     def label_from_instance(self, instance):
36         return _(instance.name)
37 
38 
39 def admin_permissions(request, current_directory, template, ctx):
40     language = ctx.get('language', None)
41 
42     negative_permissions_excl = list(PERMISSIONS['negative'])
43     positive_permissions_excl = list(PERMISSIONS['positive'])
44 
45     # Don't provide means to alter access permissions under /<lang_code>/*
46     # In other words: only allow setting access permissions for the root
47     # and the `/projects/<code>/` directories
48     if language is not None:
49         access_permissions = ['view', 'hide']
50         negative_permissions_excl.extend(access_permissions)
51         positive_permissions_excl.extend(access_permissions)
52 
53     content_type = get_permission_contenttype()
54 
55     positive_permissions_qs = content_type.permission_set.exclude(
56         codename__in=negative_permissions_excl,
57     )
58     negative_permissions_qs = content_type.permission_set.exclude(
59         codename__in=positive_permissions_excl,
60     )
61 
62     base_queryset = User.objects.filter(is_active=1).exclude(
63         id__in=current_directory.permission_sets.values_list('user_id',
64                                                              flat=True),)
65     choice_groups = [(None, base_queryset.filter(
66         username__in=('nobody', 'default')
67     ))]
68 
69     choice_groups.append((
70         _('All Users'),
71         base_queryset.exclude(username__in=('nobody',
72                                             'default')).order_by('username'),
73     ))
74 
75     class PermissionSetForm(forms.ModelForm):
76 
77         class Meta(object):
78             model = PermissionSet
79             fields = ('user', 'directory', 'positive_permissions',
80                       'negative_permissions')
81 
82         directory = forms.ModelChoiceField(
83             queryset=Directory.objects.filter(pk=current_directory.pk),
84             initial=current_directory.pk,
85             widget=forms.HiddenInput,
86         )
87         user = GroupedModelChoiceField(
88             label=_('Username'),
89             choice_groups=choice_groups,
90             queryset=User.objects.all(),
91             required=True,
92             widget=forms.Select(attrs={
93                 'class': 'js-select2 select2-username',
94             }),
95         )
96         positive_permissions = PermissionFormField(
97             label=_('Add Permissions'),
98             queryset=positive_permissions_qs,
99             required=False,
100             widget=forms.SelectMultiple(attrs={
101                 'class': 'js-select2 select2-multiple',
102                 'data-placeholder': _('Select one or more permissions'),
103             }),
104         )
105         negative_permissions = PermissionFormField(
106             label=_('Revoke Permissions'),
107             queryset=negative_permissions_qs,
108             required=False,
109             widget=forms.SelectMultiple(attrs={
110                 'class': 'js-select2 select2-multiple',
111                 'data-placeholder': _('Select one or more permissions'),
112             }),
113         )
114 
115         def __init__(self, *args, **kwargs):
116             super(PermissionSetForm, self).__init__(*args, **kwargs)
117 
118             # Don't display extra negative permissions field where they
119             # are not applicable
120             if language is not None:
121                 del self.fields['negative_permissions']
122 
123     link = lambda instance: unicode(instance.user)
124     directory_permissions = current_directory.permission_sets \
125                                              .order_by('user').all()
126 
127     return util.edit(request, template, PermissionSet, ctx, link,
128                      linkfield='user', queryset=directory_permissions,
129                      can_delete=True, form=PermissionSetForm)
130 
131 
132 class PermissionsUsersJSON(PootleJSONMixin, PootleAdminFormView):
133     form_class = PermissionsUsersSearchForm
134 
135     @property
136     def directory(self):
137         return get_object_or_404(
138             Directory.objects,
139             pk=self.kwargs["directory"])
140 
141     def get_context_data(self, **kwargs):
142         context = super(
143             PermissionsUsersJSON, self).get_context_data(**kwargs)
144         form = context["form"]
145         return (
146             dict(items=form.search())
147             if form.is_valid()
148             else dict(items=[]))
149 
150     def get_form_kwargs(self):
151         kwargs = super(PermissionsUsersJSON, self).get_form_kwargs()
152         kwargs["directory"] = self.directory
153         return kwargs
154 
155     def form_valid(self, form):
156         return self.render_to_response(
157             self.get_context_data(form=form))
158 
159     def form_invalid(self, form):
160         raise Http400(form.errors)
161
```
--- 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/pootle/apps/pootle_app/views/admin/permissions.py b/pootle/apps/pootle_app/views/admin/permissions.py
--- a/pootle/apps/pootle_app/views/admin/permissions.py
+++ b/pootle/apps/pootle_app/views/admin/permissions.py
@@ -8,11 +8,13 @@
 
 from django import forms
 from django.contrib.auth import get_user_model
+from django.urls import reverse
 
 from pootle.core.decorators import get_object_or_404
 from pootle.core.exceptions import Http400
 from pootle.core.views.admin import PootleAdminFormView
 from pootle.core.views.mixins import PootleJSONMixin
+from pootle.core.views.widgets import RemoteSelectWidget
 from pootle.i18n.gettext import ugettext as _
 from pootle_app.forms import PermissionsUsersSearchForm
 from pootle_app.models import Directory
@@ -89,10 +91,11 @@
             choice_groups=choice_groups,
             queryset=User.objects.all(),
             required=True,
-            widget=forms.Select(attrs={
-                'class': 'js-select2 select2-username',
-            }),
-        )
+            widget=RemoteSelectWidget(
+                attrs={
+                    "data-s2-placeholder": _("Search for users to add"),
+                    'class': ('js-select2-remote select2-username '
+                              'js-s2-new-members')}))
         positive_permissions = PermissionFormField(
             label=_('Add Permissions'),
             queryset=positive_permissions_qs,
@@ -115,6 +118,10 @@
         def __init__(self, *args, **kwargs):
             super(PermissionSetForm, self).__init__(*args, **kwargs)
 
+            self.fields["user"].widget.attrs["data-select2-url"] = reverse(
+                "pootle-permissions-users",
+                kwargs=dict(directory=current_directory.pk))
+
             # Don't display extra negative permissions field where they
             # are not applicable
             if language is not None:

{"golden_diff": "diff --git a/pootle/apps/pootle_app/views/admin/permissions.py b/pootle/apps/pootle_app/views/admin/permissions.py\n--- a/pootle/apps/pootle_app/views/admin/permissions.py\n+++ b/pootle/apps/pootle_app/views/admin/permissions.py\n@@ -8,11 +8,13 @@\n \n from django import forms\n from django.contrib.auth import get_user_model\n+from django.urls import reverse\n \n from pootle.core.decorators import get_object_or_404\n from pootle.core.exceptions import Http400\n from pootle.core.views.admin import PootleAdminFormView\n from pootle.core.views.mixins import PootleJSONMixin\n+from pootle.core.views.widgets import RemoteSelectWidget\n from pootle.i18n.gettext import ugettext as _\n from pootle_app.forms import PermissionsUsersSearchForm\n from pootle_app.models import Directory\n@@ -89,10 +91,11 @@\n             choice_groups=choice_groups,\n             queryset=User.objects.all(),\n             required=True,\n-            widget=forms.Select(attrs={\n-                'class': 'js-select2 select2-username',\n-            }),\n-        )\n+            widget=RemoteSelectWidget(\n+                attrs={\n+                    \"data-s2-placeholder\": _(\"Search for users to add\"),\n+                    'class': ('js-select2-remote select2-username '\n+                              'js-s2-new-members')}))\n         positive_permissions = PermissionFormField(\n             label=_('Add Permissions'),\n             queryset=positive_permissions_qs,\n@@ -115,6 +118,10 @@\n         def __init__(self, *args, **kwargs):\n             super(PermissionSetForm, self).__init__(*args, **kwargs)\n \n+            self.fields[\"user\"].widget.attrs[\"data-select2-url\"] = reverse(\n+                \"pootle-permissions-users\",\n+                kwargs=dict(directory=current_directory.pk))\n+\n             # Don't display extra negative permissions field where they\n             # are not applicable\n             if language is not None:\n", "issue": "Use XHR for user select2 widgets\non a site with a lot of users the admin widgets are very slow and unnecessarily push a full list of users\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n#\n# Copyright (C) Pootle contributors.\n#\n# This file is a part of the Pootle project. It is distributed under the GPL3\n# or later license. See the LICENSE file for a copy of the license and the\n# AUTHORS file for copyright and authorship information.\n\nfrom django import forms\nfrom django.contrib.auth import get_user_model\n\nfrom pootle.core.decorators import get_object_or_404\nfrom pootle.core.exceptions import Http400\nfrom pootle.core.views.admin import PootleAdminFormView\nfrom pootle.core.views.mixins import PootleJSONMixin\nfrom pootle.i18n.gettext import ugettext as _\nfrom pootle_app.forms import PermissionsUsersSearchForm\nfrom pootle_app.models import Directory\nfrom pootle_app.models.permissions import (PermissionSet,\n                                           get_permission_contenttype)\nfrom pootle_app.views.admin import util\nfrom pootle_misc.forms import GroupedModelChoiceField\n\n\nUser = get_user_model()\n\nPERMISSIONS = {\n    'positive': ['view', 'suggest', 'translate', 'review', 'administrate'],\n    'negative': ['hide'],\n}\n\n\nclass PermissionFormField(forms.ModelMultipleChoiceField):\n\n    def label_from_instance(self, instance):\n        return _(instance.name)\n\n\ndef admin_permissions(request, current_directory, template, ctx):\n    language = ctx.get('language', None)\n\n    negative_permissions_excl = list(PERMISSIONS['negative'])\n    positive_permissions_excl = list(PERMISSIONS['positive'])\n\n    # Don't provide means to alter access permissions under /<lang_code>/*\n    # In other words: only allow setting access permissions for the root\n    # and the `/projects/<code>/` directories\n    if language is not None:\n        access_permissions = ['view', 'hide']\n        negative_permissions_excl.extend(access_permissions)\n        positive_permissions_excl.extend(access_permissions)\n\n    content_type = get_permission_contenttype()\n\n    positive_permissions_qs = content_type.permission_set.exclude(\n        codename__in=negative_permissions_excl,\n    )\n    negative_permissions_qs = content_type.permission_set.exclude(\n        codename__in=positive_permissions_excl,\n    )\n\n    base_queryset = User.objects.filter(is_active=1).exclude(\n        id__in=current_directory.permission_sets.values_list('user_id',\n                                                             flat=True),)\n    choice_groups = [(None, base_queryset.filter(\n        username__in=('nobody', 'default')\n    ))]\n\n    choice_groups.append((\n        _('All Users'),\n        base_queryset.exclude(username__in=('nobody',\n                                            'default')).order_by('username'),\n    ))\n\n    class PermissionSetForm(forms.ModelForm):\n\n        class Meta(object):\n            model = PermissionSet\n            fields = ('user', 'directory', 'positive_permissions',\n                      'negative_permissions')\n\n        directory = forms.ModelChoiceField(\n            queryset=Directory.objects.filter(pk=current_directory.pk),\n            initial=current_directory.pk,\n            widget=forms.HiddenInput,\n        )\n        user = GroupedModelChoiceField(\n            label=_('Username'),\n            choice_groups=choice_groups,\n            queryset=User.objects.all(),\n            required=True,\n            widget=forms.Select(attrs={\n                'class': 'js-select2 select2-username',\n            }),\n        )\n        positive_permissions = PermissionFormField(\n            label=_('Add Permissions'),\n            queryset=positive_permissions_qs,\n            required=False,\n            widget=forms.SelectMultiple(attrs={\n                'class': 'js-select2 select2-multiple',\n                'data-placeholder': _('Select one or more permissions'),\n            }),\n        )\n        negative_permissions = PermissionFormField(\n            label=_('Revoke Permissions'),\n            queryset=negative_permissions_qs,\n            required=False,\n            widget=forms.SelectMultiple(attrs={\n                'class': 'js-select2 select2-multiple',\n                'data-placeholder': _('Select one or more permissions'),\n            }),\n        )\n\n        def __init__(self, *args, **kwargs):\n            super(PermissionSetForm, self).__init__(*args, **kwargs)\n\n            # Don't display extra negative permissions field where they\n            # are not applicable\n            if language is not None:\n                del self.fields['negative_permissions']\n\n    link = lambda instance: unicode(instance.user)\n    directory_permissions = current_directory.permission_sets \\\n                                             .order_by('user').all()\n\n    return util.edit(request, template, PermissionSet, ctx, link,\n                     linkfield='user', queryset=directory_permissions,\n                     can_delete=True, form=PermissionSetForm)\n\n\nclass PermissionsUsersJSON(PootleJSONMixin, PootleAdminFormView):\n    form_class = PermissionsUsersSearchForm\n\n    @property\n    def directory(self):\n        return get_object_or_404(\n            Directory.objects,\n            pk=self.kwargs[\"directory\"])\n\n    def get_context_data(self, **kwargs):\n        context = super(\n            PermissionsUsersJSON, self).get_context_data(**kwargs)\n        form = context[\"form\"]\n        return (\n            dict(items=form.search())\n            if form.is_valid()\n            else dict(items=[]))\n\n    def get_form_kwargs(self):\n        kwargs = super(PermissionsUsersJSON, self).get_form_kwargs()\n        kwargs[\"directory\"] = self.directory\n        return kwargs\n\n    def form_valid(self, form):\n        return self.render_to_response(\n            self.get_context_data(form=form))\n\n    def form_invalid(self, form):\n        raise Http400(form.errors)\n", "path": "pootle/apps/pootle_app/views/admin/permissions.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n#\n# Copyright (C) Pootle contributors.\n#\n# This file is a part of the Pootle project. It is distributed under the GPL3\n# or later license. See the LICENSE file for a copy of the license and the\n# AUTHORS file for copyright and authorship information.\n\nfrom django import forms\nfrom django.contrib.auth import get_user_model\nfrom django.urls import reverse\n\nfrom pootle.core.decorators import get_object_or_404\nfrom pootle.core.exceptions import Http400\nfrom pootle.core.views.admin import PootleAdminFormView\nfrom pootle.core.views.mixins import PootleJSONMixin\nfrom pootle.core.views.widgets import RemoteSelectWidget\nfrom pootle.i18n.gettext import ugettext as _\nfrom pootle_app.forms import PermissionsUsersSearchForm\nfrom pootle_app.models import Directory\nfrom pootle_app.models.permissions import (PermissionSet,\n                                           get_permission_contenttype)\nfrom pootle_app.views.admin import util\nfrom pootle_misc.forms import GroupedModelChoiceField\n\n\nUser = get_user_model()\n\nPERMISSIONS = {\n    'positive': ['view', 'suggest', 'translate', 'review', 'administrate'],\n    'negative': ['hide'],\n}\n\n\nclass PermissionFormField(forms.ModelMultipleChoiceField):\n\n    def label_from_instance(self, instance):\n        return _(instance.name)\n\n\ndef admin_permissions(request, current_directory, template, ctx):\n    language = ctx.get('language', None)\n\n    negative_permissions_excl = list(PERMISSIONS['negative'])\n    positive_permissions_excl = list(PERMISSIONS['positive'])\n\n    # Don't provide means to alter access permissions under /<lang_code>/*\n    # In other words: only allow setting access permissions for the root\n    # and the `/projects/<code>/` directories\n    if language is not None:\n        access_permissions = ['view', 'hide']\n        negative_permissions_excl.extend(access_permissions)\n        positive_permissions_excl.extend(access_permissions)\n\n    content_type = get_permission_contenttype()\n\n    positive_permissions_qs = content_type.permission_set.exclude(\n        codename__in=negative_permissions_excl,\n    )\n    negative_permissions_qs = content_type.permission_set.exclude(\n        codename__in=positive_permissions_excl,\n    )\n\n    base_queryset = User.objects.filter(is_active=1).exclude(\n        id__in=current_directory.permission_sets.values_list('user_id',\n                                                             flat=True),)\n    choice_groups = [(None, base_queryset.filter(\n        username__in=('nobody', 'default')\n    ))]\n\n    choice_groups.append((\n        _('All Users'),\n        base_queryset.exclude(username__in=('nobody',\n                                            'default')).order_by('username'),\n    ))\n\n    class PermissionSetForm(forms.ModelForm):\n\n        class Meta(object):\n            model = PermissionSet\n            fields = ('user', 'directory', 'positive_permissions',\n                      'negative_permissions')\n\n        directory = forms.ModelChoiceField(\n            queryset=Directory.objects.filter(pk=current_directory.pk),\n            initial=current_directory.pk,\n            widget=forms.HiddenInput,\n        )\n        user = GroupedModelChoiceField(\n            label=_('Username'),\n            choice_groups=choice_groups,\n            queryset=User.objects.all(),\n            required=True,\n            widget=RemoteSelectWidget(\n                attrs={\n                    \"data-s2-placeholder\": _(\"Search for users to add\"),\n                    'class': ('js-select2-remote select2-username '\n                              'js-s2-new-members')}))\n        positive_permissions = PermissionFormField(\n            label=_('Add Permissions'),\n            queryset=positive_permissions_qs,\n            required=False,\n            widget=forms.SelectMultiple(attrs={\n                'class': 'js-select2 select2-multiple',\n                'data-placeholder': _('Select one or more permissions'),\n            }),\n        )\n        negative_permissions = PermissionFormField(\n            label=_('Revoke Permissions'),\n            queryset=negative_permissions_qs,\n            required=False,\n            widget=forms.SelectMultiple(attrs={\n                'class': 'js-select2 select2-multiple',\n                'data-placeholder': _('Select one or more permissions'),\n            }),\n        )\n\n        def __init__(self, *args, **kwargs):\n            super(PermissionSetForm, self).__init__(*args, **kwargs)\n\n            self.fields[\"user\"].widget.attrs[\"data-select2-url\"] = reverse(\n                \"pootle-permissions-users\",\n                kwargs=dict(directory=current_directory.pk))\n\n            # Don't display extra negative permissions field where they\n            # are not applicable\n            if language is not None:\n                del self.fields['negative_permissions']\n\n    link = lambda instance: unicode(instance.user)\n    directory_permissions = current_directory.permission_sets \\\n                                             .order_by('user').all()\n\n    return util.edit(request, template, PermissionSet, ctx, link,\n                     linkfield='user', queryset=directory_permissions,\n                     can_delete=True, form=PermissionSetForm)\n\n\nclass PermissionsUsersJSON(PootleJSONMixin, PootleAdminFormView):\n    form_class = PermissionsUsersSearchForm\n\n    @property\n    def directory(self):\n        return get_object_or_404(\n            Directory.objects,\n            pk=self.kwargs[\"directory\"])\n\n    def get_context_data(self, **kwargs):\n        context = super(\n            PermissionsUsersJSON, self).get_context_data(**kwargs)\n        form = context[\"form\"]\n        return (\n            dict(items=form.search())\n            if form.is_valid()\n            else dict(items=[]))\n\n    def get_form_kwargs(self):\n        kwargs = super(PermissionsUsersJSON, self).get_form_kwargs()\n        kwargs[\"directory\"] = self.directory\n        return kwargs\n\n    def form_valid(self, form):\n        return self.render_to_response(\n            self.get_context_data(form=form))\n\n    def form_invalid(self, form):\n        raise Http400(form.errors)\n", "path": "pootle/apps/pootle_app/views/admin/permissions.py"}]}