mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-23 11:53:12 +00:00
Create Query class
This commit is contained in:
parent
5eac7f6614
commit
e51038c07b
1 changed files with 61 additions and 38 deletions
|
@ -51,6 +51,25 @@ from re2o.base import SortTable, re2o_paginator
|
||||||
from re2o.acl import can_view_all
|
from re2o.acl import can_view_all
|
||||||
|
|
||||||
|
|
||||||
|
class Query:
|
||||||
|
def __init__(self, text=""):
|
||||||
|
self.text = text # Content of the query
|
||||||
|
self.operator = None # Whether a special char (ex "+") was used
|
||||||
|
self.subqueries = None # When splitting the query in subparts (ex when using "+")
|
||||||
|
|
||||||
|
def add_char(self, char):
|
||||||
|
self.text += char
|
||||||
|
|
||||||
|
def add_operator(self, operator):
|
||||||
|
self.operator = operator
|
||||||
|
|
||||||
|
if self.subqueries is None:
|
||||||
|
self.subqueries = []
|
||||||
|
|
||||||
|
self.subqueries.append(Query(self.text))
|
||||||
|
self.text = ""
|
||||||
|
|
||||||
|
|
||||||
def is_int(variable):
|
def is_int(variable):
|
||||||
""" Check if the variable can be casted to an integer """
|
""" Check if the variable can be casted to an integer """
|
||||||
|
|
||||||
|
@ -69,7 +88,7 @@ def filter_fields():
|
||||||
|
|
||||||
def empty_filters():
|
def empty_filters():
|
||||||
"""Build empty filters used by Django"""
|
"""Build empty filters used by Django"""
|
||||||
filters = [Q() for f in filter_fields()]
|
return {f: Q() for f in filter_fields()}
|
||||||
|
|
||||||
|
|
||||||
def finish_results(request, results, col, order):
|
def finish_results(request, results, col, order):
|
||||||
|
@ -77,10 +96,12 @@ def finish_results(request, results, col, order):
|
||||||
number of max results. Finally add the info of the nmax number of results
|
number of max results. Finally add the info of the nmax number of results
|
||||||
to the dict"""
|
to the dict"""
|
||||||
|
|
||||||
results["users"] += results["clubs"]
|
|
||||||
results["users"] = SortTable.sort(
|
results["users"] = SortTable.sort(
|
||||||
results["users"], col, order, SortTable.USERS_INDEX
|
results["users"], col, order, SortTable.USERS_INDEX
|
||||||
)
|
)
|
||||||
|
results["clubs"] = SortTable.sort(
|
||||||
|
results["clubs"], col, order, SortTable.USERS_INDEX
|
||||||
|
)
|
||||||
results["machines"] = SortTable.sort(
|
results["machines"] = SortTable.sort(
|
||||||
results["machines"], col, order, SortTable.MACHINES_INDEX
|
results["machines"], col, order, SortTable.MACHINES_INDEX
|
||||||
)
|
)
|
||||||
|
@ -129,6 +150,8 @@ def search_single_word(word, filters, user, start, end, user_state, aff):
|
||||||
| Q(room__name__icontains=word)
|
| Q(room__name__icontains=word)
|
||||||
| Q(email__icontains=word)
|
| Q(email__icontains=word)
|
||||||
| Q(telephone__icontains=word)
|
| Q(telephone__icontains=word)
|
||||||
|
| Q(room__name__icontains=word)
|
||||||
|
| Q(room__building__name__icontains=word)
|
||||||
)
|
)
|
||||||
filter_users = (filter_clubs | Q(name__icontains=word))
|
filter_users = (filter_clubs | Q(name__icontains=word))
|
||||||
|
|
||||||
|
@ -213,8 +236,9 @@ def search_single_word(word, filters, user, start, end, user_state, aff):
|
||||||
# Rooms
|
# Rooms
|
||||||
if "5" in aff and Room.can_view_all(user):
|
if "5" in aff and Room.can_view_all(user):
|
||||||
filter_rooms = (
|
filter_rooms = (
|
||||||
Q(details__icontains=word) | Q(name__icontains=word) | Q(port__details=word)
|
Q(details__icontains=word) | Q(name__icontains=word) | Q(port__details=word) | Q(building__name__icontains=building)
|
||||||
)
|
)
|
||||||
|
filter_rooms |= (Q(name__icontains=room) & Q(building__name__icontains=building))
|
||||||
|
|
||||||
filters["rooms"] |= filter_rooms
|
filters["rooms"] |= filter_rooms
|
||||||
|
|
||||||
|
@ -307,22 +331,25 @@ def apply_filters(filters, user, aff):
|
||||||
def search_single_query(query, filters, user, start, end, user_state, aff):
|
def search_single_query(query, filters, user, start, end, user_state, aff):
|
||||||
""" Handle different queries an construct the correct filters using
|
""" Handle different queries an construct the correct filters using
|
||||||
search_single_word"""
|
search_single_word"""
|
||||||
if query["operator"] == "+":
|
if query.operator == "+":
|
||||||
# Special queries with "+" operators should use & rather than |
|
# Special queries with "+" operators should use & rather than |
|
||||||
for q in query["subqueries"]:
|
newfilters = empty_filters()
|
||||||
|
for q in query.subqueries:
|
||||||
# Construct an independent filter for each subquery
|
# Construct an independent filter for each subquery
|
||||||
subfilters = empty_filters()
|
subfilters = search_single_query(q, empty_filters(), user, start, end, user_state, aff)
|
||||||
subfilters = search_single_word(q, subfilters, user, start, end, user_state, aff)
|
|
||||||
|
|
||||||
# Apply the new filter
|
# Apply the subfilter
|
||||||
for field in filter_fields():
|
for field in filter_fields():
|
||||||
filters[field] &= subfilters[field]
|
newfilters[field] &= subfilters[field]
|
||||||
|
|
||||||
|
# Add these filters to the existing ones
|
||||||
|
for field in filter_fields():
|
||||||
|
filters[field] |= newfilters[field]
|
||||||
|
|
||||||
return filters
|
return filters
|
||||||
|
|
||||||
# Handle standard queries
|
# Handle standard queries
|
||||||
q = query["text"]
|
return search_single_word(query.text, filters, user, start, end, user_state, aff)
|
||||||
return search_single_word(q, filters, user, start, end, user_state, aff)
|
|
||||||
|
|
||||||
|
|
||||||
def create_queries(query):
|
def create_queries(query):
|
||||||
|
@ -338,12 +365,6 @@ def create_queries(query):
|
||||||
"""
|
"""
|
||||||
# A dict representing the different queries extracted from the user's text
|
# A dict representing the different queries extracted from the user's text
|
||||||
queries = []
|
queries = []
|
||||||
|
|
||||||
# Format: {
|
|
||||||
# "text": "", # Content of the query
|
|
||||||
# "operator": None, # Whether a special char ("+") was used
|
|
||||||
# "subqueries": None # When splitting the query in subparts (ex when using "+")
|
|
||||||
# }
|
|
||||||
current_query = None
|
current_query = None
|
||||||
|
|
||||||
# Whether the query is between "
|
# Whether the query is between "
|
||||||
|
@ -355,12 +376,12 @@ def create_queries(query):
|
||||||
for char in query:
|
for char in query:
|
||||||
if current_query is None:
|
if current_query is None:
|
||||||
# We are starting a new word
|
# We are starting a new word
|
||||||
current_query = { "text": "", "operator": None, "subqueries": None }
|
current_query = Query()
|
||||||
|
|
||||||
if escaping_char:
|
if escaping_char:
|
||||||
# The last char war a \ so we escape this char
|
# The last char war a \ so we escape this char
|
||||||
escaping_char = False
|
escaping_char = False
|
||||||
current_query["text"] += char
|
current_query.add_char(char)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if char == "\\":
|
if char == "\\":
|
||||||
|
@ -375,36 +396,28 @@ def create_queries(query):
|
||||||
|
|
||||||
if keep_intact:
|
if keep_intact:
|
||||||
# If we are between two ", ignore separators
|
# If we are between two ", ignore separators
|
||||||
current_query["text"] += char
|
current_query.add_char(char)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if char == "+":
|
if char == "+":
|
||||||
# Can't sart a query with a "+", consider it escaped
|
if len(current_query.text) == 0:
|
||||||
if len(current_query["text"]) == 0:
|
# Can't sart a query with a "+", consider it escaped
|
||||||
current_query["text"] = char
|
current_query.add_char(char)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Build a slightly more complicate data structure
|
current_query.add_operator("+")
|
||||||
# This is need for queries like '"A B"+C'
|
|
||||||
if current_query["operator"] is None:
|
|
||||||
current_query["operator"] = "+"
|
|
||||||
current_query["subqueries"] = []
|
|
||||||
|
|
||||||
current_query["subqueries"].append(current_query["text"])
|
|
||||||
current_query["text"] = ""
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if char == " " or char == ",":
|
if char == " " or char == ",":
|
||||||
# If we encouter a separator outside of ", we create a new word
|
# If we encouter a separator outside of ", we create a new word
|
||||||
|
|
||||||
if len(current_query["text"]) == 0:
|
if len(current_query.text) == 0:
|
||||||
# Discard empty queries
|
# Discard empty queries
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if current_query["operator"] is not None:
|
if current_query.operator is not None:
|
||||||
# If we were building a special structure, finish building it
|
# If we were building a special structure, finish building it
|
||||||
current_query["subqueries"].append(current_query["text"])
|
current_query.add_operator(current_query.operator)
|
||||||
current_query["text"] = ""
|
|
||||||
|
|
||||||
# Save the query and start a new one
|
# Save the query and start a new one
|
||||||
queries.append(current_query)
|
queries.append(current_query)
|
||||||
|
@ -412,7 +425,17 @@ def create_queries(query):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# If we haven't encountered any special case, add the char to the word
|
# If we haven't encountered any special case, add the char to the word
|
||||||
current_query["text"].append(char)
|
current_query.add_char(char)
|
||||||
|
|
||||||
|
# Save the current working query if necessary
|
||||||
|
if current_query is not None:
|
||||||
|
if current_query.operator is not None:
|
||||||
|
# There was an operator supposed to split multiple words
|
||||||
|
if len(current_query.text) > 0:
|
||||||
|
# Finish the current search
|
||||||
|
current_query.add_operator(current_query.operator)
|
||||||
|
|
||||||
|
queries.append(current_query)
|
||||||
|
|
||||||
return queries
|
return queries
|
||||||
|
|
||||||
|
@ -431,9 +454,9 @@ def get_results(query, request, params):
|
||||||
filters = empty_filters()
|
filters = empty_filters()
|
||||||
|
|
||||||
queries = create_queries(query)
|
queries = create_queries(query)
|
||||||
for query in queries:
|
for q in queries:
|
||||||
filters = search_single_query(
|
filters = search_single_query(
|
||||||
query, filters, request.user, start, end, user_state, aff
|
q, filters, request.user, start, end, user_state, aff
|
||||||
)
|
)
|
||||||
|
|
||||||
results = apply_filters(filters, request.user, aff)
|
results = apply_filters(filters, request.user, aff)
|
||||||
|
|
Loading…
Reference in a new issue