This repository was archived by the owner on Dec 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathadmin.py
76 lines (60 loc) · 2.64 KB
/
admin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from functools import reduce
from operator import or_
from typing import List
from django.conf.urls import url
from django.contrib import admin
from django.db.models import Q, Model
from django.http import HttpRequest
from django.urls.resolvers import URLPattern
try:
from django.urls import reverse
except ImportError:
from django.core.urlresolvers import reverse # type: ignore
from django.http.response import HttpResponse, JsonResponse, HttpResponseBadRequest
class SearchAutoCompleteAdmin(admin.ModelAdmin):
"""
Basic admin class that allows to enable search autocomplete for certain model.
Usage:
.. code-block:: python
class MyModelAdmin(SearchAutoCompleteAdmin)
search_fields = ['search_field', ]
admin.site.register(MyModel, MyModelAdmin)
"""
change_list_template = 'search_admin_autocomplete/change_list.html'
search_fields = [] # type: List[str]
search_prefix = '__contains'
max_results = 10
def get_urls(self) -> List[URLPattern]:
urls = super(SearchAutoCompleteAdmin, self).get_urls()
api_urls = [url(r'^search/(?P<search_term>\w{0,50})$', self.search_api)]
return api_urls + urls
def search_api(self, request: HttpRequest, search_term: str) -> HttpResponse:
"""
API view that perform search by search term for current model.
"""
if len(self.search_fields) == 0:
return HttpResponseBadRequest(reason='Mo search_fields defined in {}'.format(self.__class__.__name__))
query = [Q(**{'{}{}'.format(field, self.search_prefix): search_term}) for field in self.search_fields]
# https://github.com/python/mypy/issues/4150
query = reduce(or_, query) # type: ignore
return JsonResponse(data=[{'keyword': self.get_instance_name(item), 'url': self.get_instance_url(item)}
for item in self.model.objects.filter(query)[0:self.max_results]], safe=False)
def get_instance_name(self, instance: Model) -> str:
"""
Format instance name based on value of search fields.
"""
values = []
for field in self.search_fields:
value = getattr(instance, field)
if not value:
continue
values.append(str(value))
if not values:
return ""
return ", ".join(values)
def get_instance_url(self, instance: Model) -> str:
"""
Returns url admin change view for model instance.
"""
url_name = "admin:{}_{}_change".format(self.model._meta.app_label, str(self.model.__name__).lower())
return reverse(url_name, args=(instance.pk,))