mirror of
https://github.com/peeringdb/peeringdb.git
synced 2024-05-11 05:55:09 +00:00
* django3, py39, lgtm, linting (#715) * IX-F Importer: ticket status change when posting re-occuring conflict to existing resolved ticket (#920) * fix recaptcha requirement for user creation in django-admin (#715) * IX-F Importer: fix command output buffering #967 * Drop dot1q_support field #903 * fix test (#967) * Add name, city, country to ixfac (GET operation) #166 * additional tests fir #166 * Allow IXP to trigger ix-f importer for their exchange #779 * add docker compose for dev * add selinux labels for mountpoints * fixes #1013: The process to permanently remove old soft-deleted network contacts pdb_delete_pocs raises a false ProtectedAction * fix api test * relock poetry * remove django_namespace_perms from installed apps * fix user permissios ui * remove remaining references to django namespace perms * linting * copy tox.ini * comment flake8 check until we figure out why it ignores configs from tox.ini * black format * poetry lock Co-authored-by: Stefan Pratter <stefan@20c.com>
153 lines
3.4 KiB
Python
153 lines
3.4 KiB
Python
# import time
|
|
import unidecode
|
|
from django.conf import settings
|
|
from django.db.models import Q
|
|
from haystack.inputs import Exact
|
|
from haystack.query import SearchQuerySet
|
|
|
|
from peeringdb_server.models import (
|
|
Facility,
|
|
InternetExchange,
|
|
IXLanPrefix,
|
|
Network,
|
|
NetworkIXLan,
|
|
Organization,
|
|
)
|
|
|
|
# models considered during autocomplete (quick-search)
|
|
|
|
autocomplete_models = [
|
|
Organization,
|
|
Network,
|
|
InternetExchange,
|
|
Facility,
|
|
]
|
|
|
|
# models considered during standard search
|
|
|
|
searchable_models = [
|
|
Organization,
|
|
Network,
|
|
Facility,
|
|
InternetExchange,
|
|
NetworkIXLan,
|
|
IXLanPrefix,
|
|
# InternetExchangeFacility,
|
|
# NetworkFacility,
|
|
# NetworkContact,
|
|
# IXLan,
|
|
]
|
|
|
|
|
|
def unaccent(v):
|
|
return unidecode.unidecode(v).lower()
|
|
|
|
|
|
def prepare_term(term):
|
|
try:
|
|
if len(term) == 1:
|
|
int(term)
|
|
term = f"AS{term}"
|
|
except ValueError:
|
|
pass
|
|
|
|
return unaccent(term)
|
|
|
|
|
|
def make_search_query(term):
|
|
if not term:
|
|
return SearchQuerySet().none()
|
|
|
|
term = prepare_term(term)
|
|
|
|
term_filters = Q(content=term) | Q(content__startswith=term)
|
|
|
|
return SearchQuerySet().filter(term_filters, status=Exact("ok"))
|
|
|
|
|
|
def make_name_search_query(term):
|
|
if not term:
|
|
return SearchQuerySet().none()
|
|
|
|
term = prepare_term(term)
|
|
|
|
term_filters = Q(name=term) | Q(name__startswith=term)
|
|
|
|
return SearchQuerySet().filter(term_filters, status=Exact("ok"))
|
|
|
|
|
|
def make_autocomplete_query(term):
|
|
if not term:
|
|
return SearchQuerySet().none()
|
|
|
|
term = prepare_term(term)
|
|
return SearchQuerySet().autocomplete(auto=term).filter(status=Exact("ok"))
|
|
|
|
|
|
def search(term, autocomplete=False):
|
|
"""
|
|
Search searchable objects (ixp, network, facility ...) by term
|
|
|
|
Returns result dict
|
|
"""
|
|
|
|
# t0 = time.time()
|
|
|
|
if autocomplete:
|
|
search_query = make_autocomplete_query(term).models(*autocomplete_models)
|
|
limit = settings.SEARCH_RESULTS_AUTOCOMPLETE_LIMIT
|
|
else:
|
|
search_query = make_search_query(term).models(*searchable_models)
|
|
limit = settings.SEARCH_RESULTS_LIMIT
|
|
|
|
categories = ("fac", "ix", "net", "org")
|
|
result = {tag: [] for tag in categories}
|
|
pk_map = {tag: {} for tag in categories}
|
|
|
|
for sq in search_query[:limit]:
|
|
model = sq.model
|
|
model.HandleRef.tag
|
|
|
|
categorize(sq, result, pk_map)
|
|
|
|
# print("done", time.time() - t0)
|
|
|
|
return result
|
|
|
|
|
|
def categorize(sq, result, pk_map):
|
|
|
|
if getattr(sq, "result_name", None):
|
|
# main entity
|
|
tag = sq.model.HandleRef.tag
|
|
if tag == "org":
|
|
org_id = int(sq.pk)
|
|
else:
|
|
org_id = sq.org_id
|
|
append_result(tag, int(sq.pk), sq.result_name, org_id, None, result, pk_map)
|
|
return
|
|
|
|
# secondary entities
|
|
|
|
for tag in result.keys():
|
|
if not getattr(sq, f"{tag}_result_name", None):
|
|
continue
|
|
|
|
org_id = int(getattr(sq, f"{tag}_org_id", 0))
|
|
name = getattr(sq, f"{tag}_result_name")
|
|
pk = int(getattr(sq, f"{tag}_id", 0))
|
|
sub_name = getattr(sq, f"{tag}_sub_result_name")
|
|
append_result(tag, pk, name, org_id, sub_name, result, pk_map)
|
|
|
|
|
|
def append_result(tag, pk, name, org_id, sub_name, result, pk_map):
|
|
|
|
if pk in pk_map[tag]:
|
|
return
|
|
|
|
pk_map[tag][pk] = True
|
|
|
|
result[tag].append(
|
|
{"id": pk, "name": name, "org_id": int(org_id), "sub_name": sub_name}
|
|
)
|