mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-10 17:16:22 +01:00
refactor
This commit is contained in:
@@ -12,54 +12,80 @@ from allianceauth.services.hooks import get_extension_logger
|
|||||||
logger = get_extension_logger(__name__)
|
logger = get_extension_logger(__name__)
|
||||||
|
|
||||||
class DataTablesView(View):
|
class DataTablesView(View):
|
||||||
"""
|
|
||||||
Basic DataTables server side table rendering
|
|
||||||
"""
|
|
||||||
model: Model = None
|
model: Model = None
|
||||||
templates: list[str] = []
|
|
||||||
columns: list[tuple] = []
|
columns: list[tuple] = []
|
||||||
|
|
||||||
|
COL_SEARCH_REGEX = r"columns\[(?P<id>[0-9]{1,})\]\[search\]\[value\]"
|
||||||
|
COL_SEARCHABLE_REGEX = r"columns\[(?P<id>[0-9]{1,})\]\[searchable\]"
|
||||||
|
COL_SEARCHABLE_AS_REGEX_REGEX = r"columns\[(?P<id>[0-9]{1,})\]\[search\]\[regex\]"
|
||||||
|
COL_ORDERABLE_REGEX = r"columns\[(?P<id>[0-9]{1,})\]\[orderable\]"
|
||||||
|
|
||||||
|
search_regex: re.Pattern = None
|
||||||
|
searchable_regex: re.Pattern = None
|
||||||
|
searchable_as_regex_regex: re.Pattern = None
|
||||||
|
order_regex: re.Pattern = None
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.search_regex = re.compile(self.COL_SEARCH_REGEX)
|
||||||
|
self.searchable_regex = re.compile(self.COL_SEARCHABLE_REGEX)
|
||||||
|
self.searchable_as_regex_regex = re.compile(self.COL_SEARCHABLE_AS_REGEX_REGEX)
|
||||||
|
self.order_regex = re.compile(self.COL_ORDERABLE_REGEX)
|
||||||
|
|
||||||
def get_model_qs(self, request: HttpRequest):
|
def get_model_qs(self, request: HttpRequest):
|
||||||
return self.model.objects
|
return self.model.objects
|
||||||
|
|
||||||
def get_param(self, request: HttpRequest, key: str, cast=str, default=""):
|
def get_param(self, request: HttpRequest, key: str, cast=str, default=""):
|
||||||
return cast(request.GET.get(key, default))
|
return cast(request.GET.get(key, default))
|
||||||
|
|
||||||
def filter_qs(self, search_string: str):
|
def filter_qs(self, search_string: str, column_conf: dict):
|
||||||
# Global Search
|
# Search
|
||||||
filter_q = Q()
|
filter_q = Q()
|
||||||
if len(search_string) > 0:
|
for id, c in column_conf.items():
|
||||||
val = search_string
|
_c = self.columns[id][0]
|
||||||
for x in self.columns:
|
if c["searchable"] and len(_c) > 0:
|
||||||
if x[0]:
|
if len(c["search"]) and len(_c):
|
||||||
# Apply search to all Columns
|
if c["regex"]:
|
||||||
filter_q |= Q(**{f'{x[1]}__icontains': val})
|
filter_q |= Q(**{f'{_c}__iregex': c["search"]})
|
||||||
|
else:
|
||||||
|
filter_q |= Q(**{f'{_c}__icontains': c["search"]})
|
||||||
|
if len(search_string) > 0:
|
||||||
|
filter_q |= Q(**{f'{_c}__icontains': search_string})
|
||||||
return filter_q
|
return filter_q
|
||||||
|
|
||||||
def filter_col_qs(self, get: dict):
|
def get_columns_config(self, get: dict):
|
||||||
# Row Search
|
columns = defaultdict(
|
||||||
# TODO check if we have a regex search or not
|
lambda: {
|
||||||
# TODO check if searchable or not
|
"searchable": False,
|
||||||
col_id_regex = r"columns\[(?P<id>[0-9]{1,})\]\[search\]\[value\]"
|
"orderable": False,
|
||||||
regex = re.compile(col_id_regex)
|
"regex": False,
|
||||||
filter_q = Q()
|
"search": ""
|
||||||
|
}
|
||||||
|
)
|
||||||
for c in get:
|
for c in get:
|
||||||
_r = regex.findall(c)
|
_r = self.search_regex.findall(c)
|
||||||
if _r:
|
if _r:
|
||||||
_c = self.columns[int(_r[0])]
|
columns[int(_r[0])]["search"] = get[c]
|
||||||
if _c[0]:
|
_r_s = self.searchable_regex.findall(c)
|
||||||
if len(get[c]):
|
if _r_s:
|
||||||
filter_q |= Q(**{f'{_c[1]}__iregex': get[c]})
|
columns[int(_r_s[0])]["searchable"] = get[c] == "true"
|
||||||
return filter_q
|
_r_s_r = self.searchable_as_regex_regex.findall(c)
|
||||||
|
if _r_s_r:
|
||||||
|
columns[int(_r_s_r[0])]["regex"] = get[c] == "true"
|
||||||
|
_r_o = self.order_regex.findall(c)
|
||||||
|
if _r_o:
|
||||||
|
columns[int(_r_o[0])]["orderable"] = get[c] == "true"
|
||||||
|
return columns
|
||||||
|
|
||||||
def order_str(self, order_col, order_dir):
|
def order_str(self, order_col, order_dir, column_conf: dict):
|
||||||
order = ""
|
order = ""
|
||||||
_o = self.columns[order_col]
|
_o = column_conf[order_col]
|
||||||
if _o[0]:
|
if _o["orderable"]:
|
||||||
if order_dir == 'desc':
|
if order_dir == 'desc':
|
||||||
order = '-' + _o[1]
|
order = '-' + self.columns[order_col][0]
|
||||||
else:
|
else:
|
||||||
order = _o[1]
|
order = self.columns[order_col][0]
|
||||||
return order
|
return order
|
||||||
|
|
||||||
def render_template(self, request: HttpRequest, template: str, ctx: dict):
|
def render_template(self, request: HttpRequest, template: str, ctx: dict):
|
||||||
@@ -85,24 +111,26 @@ class DataTablesView(View):
|
|||||||
|
|
||||||
limit = start + length
|
limit = start + length
|
||||||
|
|
||||||
|
column_conf = self.get_columns_config(request.GET)
|
||||||
|
|
||||||
# Searches
|
# Searches
|
||||||
filter_q = Q() | self.filter_qs(search_string) | self.filter_col_qs(request.GET)
|
filter_q = Q() | self.filter_qs(search_string, column_conf)
|
||||||
|
|
||||||
# Build response rows
|
# Build response rows
|
||||||
items = []
|
items = []
|
||||||
qs = self.get_model_qs(request).filter(filter_q).order_by()
|
qs = self.get_model_qs(request).filter(filter_q).order_by()
|
||||||
|
|
||||||
# Apply ordering
|
# Apply ordering
|
||||||
order = self.order_str(order_col, order_dir)
|
order = self.order_str(order_col, order_dir, column_conf)
|
||||||
if order != "":
|
if order != "":
|
||||||
qs = qs.order_by(order)
|
qs = qs.order_by(order)
|
||||||
|
|
||||||
# build output
|
# build output
|
||||||
for row in qs[start:limit]:
|
for row in qs[start:limit]:
|
||||||
ctx = {"row": row}
|
ctx = {"note": row}
|
||||||
row = []
|
row = []
|
||||||
for t in self.templates:
|
for t in self.columns:
|
||||||
row.append(self.render_template(request, t, ctx))
|
row.append(self.render_template(request, t[1], ctx))
|
||||||
items.append(row)
|
items.append(row)
|
||||||
|
|
||||||
# Build our output dict
|
# Build our output dict
|
||||||
|
|||||||
@@ -130,22 +130,17 @@ from allianceauth.eveonline.models import EveCharacter
|
|||||||
## Datatables server side view
|
## Datatables server side view
|
||||||
class EveCharacterTable(DataTablesView):
|
class EveCharacterTable(DataTablesView):
|
||||||
model = EveCharacter
|
model = EveCharacter
|
||||||
# Columns are rendered from these templates
|
|
||||||
# Templates can be a html file or template language directly in the list below
|
|
||||||
templates = [
|
|
||||||
"appname/stubs/icon.html",
|
|
||||||
"appname/stubs/name.html",
|
|
||||||
"appname/stubs/corp.html",
|
|
||||||
"{{ row.alliance_name }} {{ row.alliance_id }}"
|
|
||||||
]
|
|
||||||
|
|
||||||
# Define the columns for filtering and ordering
|
# Define the columns as a tuple.
|
||||||
|
# String for field name for filtering and ordering
|
||||||
|
# String for the render template
|
||||||
|
# Templates can be a html file or template language directly in the list below
|
||||||
columns = [
|
columns = [
|
||||||
# (can_sort: bool, "field_for_queries_or_sort")
|
# ("field_for_queries_or_sort", template: str)
|
||||||
(False, ""),
|
("", "appname/stubs/icon.html"),
|
||||||
(True, "character_name"),
|
("character_name", "appname/stubs/name.html"),
|
||||||
(True, "corporation_name"),
|
("corporation_name", "appname/stubs/corp.html"),
|
||||||
(True, "alliance_name"),
|
("alliance_name", "{{ row.alliance_name }} {{ row.alliance_id }}"),
|
||||||
]
|
]
|
||||||
|
|
||||||
# if you need to do some prefetch or pre-filtering you can overide this function
|
# if you need to do some prefetch or pre-filtering you can overide this function
|
||||||
|
|||||||
Reference in New Issue
Block a user