diff --git a/search/engine.py b/search/engine.py index ae772514..a724cd8c 100644 --- a/search/engine.py +++ b/search/engine.py @@ -42,6 +42,20 @@ from preferences.models import GeneralOption from re2o.base import SortTable, re2o_paginator +# List of fields the search applies to +FILTER_FIELDS = [ + "users", + "clubs", + "machines", + "factures", + "bans", + "whitelists", + "rooms", + "ports", + "switches", +] + + class Query: """Class representing a query. It can contain the user-entered text, the operator for the query, @@ -53,6 +67,7 @@ class Query: subqueries: list of Query objects when the current query is split in several parts. """ + def __init__(self, text="", case_sensitive=False): """Initialise an instance of Query. @@ -98,27 +113,14 @@ class Query: return self.operator.join([q.plaintext for q in self.subqueries]) if self.case_sensitive: - return "\"{}\"".format(self.text) + return '"{}"'.format(self.text) return self.text -def filter_fields(): - """Return the list of fields the search applies to.""" - return ["users", - "clubs", - "machines", - "factures", - "bans", - "whitelists", - "rooms", - "ports", - "switches"] - - def empty_filters(): """Build empty filters used by Django.""" - return {f: Q() for f in filter_fields()} + return {f: Q() for f in FILTER_FIELDS} def is_int(variable): @@ -176,10 +178,9 @@ def finish_results(request, results, col, order): max_result = GeneralOption.get_cached_value("search_display_page") for name, val in results.items(): page_arg = name + "_page" - results[name] = re2o_paginator(request, - val.distinct(), - max_result, - page_arg=page_arg) + results[name] = re2o_paginator( + request, val.distinct(), max_result, page_arg=page_arg + ) results.update({"max_result": max_result}) @@ -206,9 +207,9 @@ def contains_filter(attribute, word, case_sensitive=False): return Q(**{attr: word}) -def search_single_word(word, filters, user, start, end, - user_state, email_state, aff, - case_sensitive=False): +def search_single_word( + word, filters, user, start, end, user_state, email_state, aff, case_sensitive=False +): """Construct the correct filters to match differents fields of some models with the given query according to the given filters. The match fields are either CharField or IntegerField that will be displayed @@ -230,10 +231,7 @@ def search_single_word(word, filters, user, start, end, ) # Users have a name whereas clubs only have a surname - filter_users = ( - filter_clubs - | contains_filter("name", word, case_sensitive) - ) + filter_users = filter_clubs | contains_filter("name", word, case_sensitive) if not User.can_view_all(user)[0]: filter_clubs &= Q(id=user.id) @@ -252,12 +250,15 @@ def search_single_word(word, filters, user, start, end, if "1" in aff: filter_machines = ( contains_filter("name", word, case_sensitive) - | (contains_filter("user__pseudo", word, case_sensitive) - & Q(user__state__in=user_state) - & Q(user__email_state__in=email_state)) + | ( + contains_filter("user__pseudo", word, case_sensitive) + & Q(user__state__in=user_state) + & Q(user__email_state__in=email_state) + ) | contains_filter("interface__domain__name", word, case_sensitive) - | contains_filter("interface__domain__related_domain__name", - word, case_sensitive) + | contains_filter( + "interface__domain__related_domain__name", word, case_sensitive + ) | contains_filter("interface__mac_address", word, case_sensitive) | contains_filter("interface__ipv4__ipv4", word, case_sensitive) ) @@ -339,13 +340,12 @@ def search_single_word(word, filters, user, start, end, # Switch ports if "6" in aff and User.can_view_all(user): filter_ports = ( - contains_filter("machine_interface__domain__name", - word, case_sensitive) - | contains_filter("related__switch__interface__domain__name", - word, case_sensitive) + contains_filter("machine_interface__domain__name", word, case_sensitive) + | contains_filter( + "related__switch__interface__domain__name", word, case_sensitive + ) | contains_filter("custom_profile__name", word, case_sensitive) - | contains_filter("custom_profile__profil_default", - word, case_sensitive) + | contains_filter("custom_profile__profil_default", word, case_sensitive) | contains_filter("details", word, case_sensitive) # Added through annotate | contains_filter("room_full_name", word, case_sensitive) @@ -360,8 +360,7 @@ def search_single_word(word, filters, user, start, end, filter_switches = ( contains_filter("interface__domain__name", word, case_sensitive) | contains_filter("interface__ipv4__ipv4", word, case_sensitive) - | contains_filter("switchbay__building__name", - word, case_sensitive) + | contains_filter("switchbay__building__name", word, case_sensitive) | contains_filter("stack__name", word, case_sensitive) | contains_filter("model__reference", word, case_sensitive) | contains_filter("model__constructor__name", word, case_sensitive) @@ -399,13 +398,11 @@ def apply_filters(filters, user, aff): # Users and clubs if "0" in aff: results["users"] = Adherent.objects.annotate( - room_full_name=Concat("room__building__name", - Value(" "), "room__name"), + room_full_name=Concat("room__building__name", Value(" "), "room__name"), room_full_name_stuck=Concat("room__building__name", "room__name"), ).filter(filters["users"]) results["clubs"] = Club.objects.annotate( - room_full_name=Concat("room__building__name", - Value(" "), "room__name"), + room_full_name=Concat("room__building__name", Value(" "), "room__name"), room_full_name_stuck=Concat("room__building__name", "room__name"), ).filter(filters["clubs"]) @@ -435,8 +432,7 @@ def apply_filters(filters, user, aff): # Switch ports if "6" in aff and User.can_view_all(user): results["ports"] = Port.objects.annotate( - room_full_name=Concat("room__building__name", - Value(" "), "room__name"), + room_full_name=Concat("room__building__name", Value(" "), "room__name"), room_full_name_stuck=Concat("room__building__name", "room__name"), ).filter(filters["ports"]) @@ -455,24 +451,32 @@ def search_single_query(query, filters, user, start, end, user_state, email_stat newfilters = empty_filters() for q in query.subqueries: # Construct an independent filter for each subquery - subfilters = search_single_query(q, empty_filters(), user, - start, end, user_state, - email_state, aff) + subfilters = search_single_query( + q, empty_filters(), user, start, end, user_state, email_state, aff + ) # Apply the subfilter - for field in filter_fields(): + for field in FILTER_FIELDS: newfilters[field] &= subfilters[field] # Add these filters to the existing ones - for field in filter_fields(): + for field in FILTER_FIELDS: filters[field] |= newfilters[field] return filters # Handle standard queries - return search_single_word(query.text, filters, user, start, end, - user_state, email_state, aff, - query.case_sensitive) + return search_single_word( + query.text, + filters, + user, + start, + end, + user_state, + email_state, + aff, + query.case_sensitive, + ) def create_queries(query):