import itertools from collections import OrderedDict from functools import update_wrapper from django.contrib import admin from django.urls import reverse from django.shortcuts import render, redirect from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ from .dashboard import * from .options import * from ..core import accounts, services # monkey-patch admin.site in order to porvide some extra admin urls urls = [] def register_url(pattern, view, name=""): global urls urls.append((pattern, view, name)) admin.site.register_url = register_url site_get_urls = admin.site.get_urls def get_urls(): def wrap(view, cacheable=False): def wrapper(*args, **kwargs): return admin.site.admin_view(view, cacheable)(*args, **kwargs) wrapper.admin_site = admin.site return update_wrapper(wrapper, view) global urls extra_patterns = [] for pattern, view, name in urls: extra_patterns.append( url(pattern, wrap(view), name=name) ) return site_get_urls() + extra_patterns admin.site.get_urls = get_urls def get_model(model_name, model_name_map): try: return model_name_map[model_name.lower()] except KeyError: return def search(request): query = request.GET.get('q', '') search_term = query models = set() selected_models = set() model_name_map = {} for service in itertools.chain(services, accounts): if service.search: models.add(service.model) model_name_map[service.model._meta.model_name] = service.model # Account direct access if search_term.endswith('!'): from ..contrib.accounts.models import Account search_term = search_term.replace('!', '') try: account = Account.objects.get(username=search_term) except Account.DoesNotExist: pass else: account_url = reverse('admin:accounts_account_change', args=(account.pk,)) return redirect(account_url) # Search for specific model elif ':' in search_term: new_search_term = [] for part in search_term.split(): if ':' in part: model_name, term = part.split(':') model = get_model(model_name, model_name_map) # Retry with singular version if model is None and model_name.endswith('s'): model = get_model(model_name[:-1], model_name_map) if model is None: new_search_term.append(':'.join((model_name, term))) else: selected_models.add(model) new_search_term.append(term) else: new_search_term.append(part) search_term = ' '.join(new_search_term) if selected_models: models = selected_models results = OrderedDict() models = sorted(models, key=lambda m: m._meta.verbose_name_plural.lower()) total = 0 for model in models: try: modeladmin = admin.site._registry[model] except KeyError: pass else: qs = modeladmin.get_queryset(request) qs, search_use_distinct = modeladmin.get_search_results(request, qs, search_term) if search_use_distinct: qs = qs.distinct() num = len(qs) if num: total += num results[model._meta] = qs title = _("{total} search results for '{query}'").format(total=total, query=query) context = { 'title': mark_safe(title), 'total': total, 'columns': min(int(total/17), 3), 'query': query, 'search_term': search_term, 'results': results, 'search_autofocus': True, } return render(request, 'admin/orchestra/search.html', context) admin.site.register_url(r'^search/$', search, 'orchestra_search_view')