""" Paramecio2fm is a series of wrappers for Flask, mako and others and construct a simple headless cms. Copyright (C) 2023 Antonio de la Rosa Caballero This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ #By default id is not showed from paramecio2.libraries.pages import Pages from paramecio2.libraries.urls import add_get_parameters from paramecio2.libraries.i18n import I18n, PGetText #from flask import request, session from paramecio2.libraries.get_data import get_query_args import sys import re pgettext=PGetText(__file__) _=pgettext.gettext class SimpleList: """Class for create item list from a model table """ def __init__(self, model, url, t): """Class for create item list from a model table You can create lists using a WebModel. You can select the show fields, and you have features how order by field and simple searchs. Args: model (WebModel): A WebModel model (equivalent to database mysql table) url (str): A string with the base url for the forms. t (PTemplate): Template used for the class. Normally template subclassed from admin_t PTemplate Attributes: raw_query (boolean): If True then raw query is done, if False then query with all related fields is done t (PTemplate): Template used for the class. Normally template subclassed from admin_t PTemplate model (WebModel): The webmodel used for generate the admin model form fields (list): A list with fields names of model getting of db query fields_showed (list): A list with fields names of model showed in list url (str): Base url used by SimpleList for generate edit, insert and other urls. limit_pages (int): The number of items by page. By default, 20 items order_defaults (list): Internal list used for define Ascendent and Descendent in sql queries order_class (list): Internal list used for show icons for ascendent or descendent field selection order (str): Default order used in order_defaults list order_field (str): The default field used for order the list. By default is the model id field order_by (str): The default order ASC or DESC defined in order_class list. By default is 0 or ASC change_order (dict): Internal dict used for get all ordenable fields from model yes_search (boolean): If True, a search form is showed, if False, the search form is hidden. search_text (str): Used for save the search text sended via POST. initial_num_pages (int): Initial number of pages showed in pagination. table_div (boolean): If True, use div for create the table, if False, use standard html table for create the table. begin_page (int): Number that is used for begin the elements to get from query search_fields (list): The fields used for search data in form. arr_extra_fields (list): List with the names of extra fields arr_extra_options (list): List with a set of functions used how extra fields. This functions return lists with different options, joined with jln attribute. jln (list): Jump line for join options by default. ajax (boolean): If True, ajax is used for get items for the list and change page, if False, typical httpd request is used for change the items page. """ self.raw_query=True self.t=t self.model=model #if len(self.model.forms)==0: #self.model.create_forms() self.fields=model.fields.keys() self.fields_showed=self.fields self.url=url self.limit_pages=20 self.order_defaults=['ASC', 'DESC'] self.order_class=['down', 'up'] #self.s=get_session() #clean session self.order='0' self.order_field=self.model.name_field_id self.order_by=self.order_defaults[0] self.change_order={} self.yes_search=True self.search_text='' self.initial_num_pages=20 self.table_div=False try: #self.begin_page=int(request.args.get('begin_page', '0')) self.begin_page=int(get_query_args('begin_page', '0')) except ValueError: self.begin_page=0 if self.begin_page<0: self.begin_page=0 self.search_fields=self.fields #self.yes_options=True self.arr_extra_fields=[_('Options')] self.arr_extra_options=[SimpleList.standard_options] self.jln='
' self.ajax=False def restore_fields(self): """Simple method for restore default fields from model """ self.fields=self.model.fields.keys() def obtain_order(self): """Function for set the order query defaults for list from http request query args. """ #self.order=request.args.get('order', self.order) #self.getpostfiles.get.get('order', self.order) self.order=get_query_args('order', self.order) order_k=int(self.order) #Obtain from get """ if 'order' in request.query.keys(): """ #order_k=int(request.query.get('order', 0)) if order_k>1 or order_k<0: order_k=0 self.order_by=self.order_defaults[ order_k ] self.order=order_k def obtain_field_search(self): """Function for set the field search query defaults for list from http request query args. """ self.order_field=get_query_args('order_field', self.order_field) field_k=self.order_field """ if 'order_field' in request.query.keys(): field_k=request.query.order_field """ if field_k in self.model.fields.keys(): self.order_field=field_k for field in self.fields: #Initialize foreignkeyfield fields too if type(self.model.fields[field]).__name__=='ForeignKeyField': name_related=self.model.fields[field].related_model.name for k in self.model.fields[field].related_model.fields.keys(): self.change_order[field+'_'+k]=self.order self.change_order[field]=self.order if self.order==0: self.change_order[field_k]=1 else: self.change_order[field_k]=0 #self.order_field=self.order_field def search(self): """Function for set the text order query defaults for list from http request query args. """ self.search_text=get_query_args('search_text', '') self.search_text=self.search_text.replace('"', '"') #self.model.conditions='AND self.search_field=get_query_args('search_field', '') if self.search_field not in self.model.fields.keys(): self.search_field='' if self.search_field!='' and self.search_text!='': self.model.conditions[0]+=' AND '+self.search_field+' LIKE %s' self.model.conditions[1].append('%'+self.search_text+'%') pass def set_options(self, options_func, arr_row): """Method for join options list returns with jln attributte separator Returns: options (str): Return a string with joined options """ #SimpleList.standard_options(arr_row) return self.jln.join(options_func(self.url, arr_row[self.model.name_field_id], arr_row)) @staticmethod def standard_options(url, id, arr_row): """Static method for get standar options for make things with the items row. Returns: options (list): Return a list of basic options for items row """ options=[] options.append(''+_('Edit')+'') options.append(''+_('Delete')+'') return options def show(self): """Method for show the table The principal method of the class. The list is showed with the selected fields, search form, pagination... """ self.model.yes_reset_conditions=False self.obtain_order() self.obtain_field_search() self.search() total_elements=self.model.select_count() num_elements=self.limit_pages link=add_get_parameters(self.url, search_text=self.search_text, search_field=self.search_field, order=self.order) begin_page=self.begin_page self.model.order_by='order by '+self.order_field+' '+self.order_by if self.limit_pages>0: self.model.limit='limit '+str(begin_page)+','+str(self.limit_pages) list_items=self.model.select(self.fields, self.raw_query) #print(self.model.fields.keys()) func_jscript='' if self.ajax==True: func_jscript='get_page()' pages='' if self.limit_pages>0: pages=Pages.show( begin_page, total_elements, num_elements, link ,initial_num_pages=self.initial_num_pages, variable='begin_page', label='', func_jscript='') self.begin_page=str(self.begin_page) self.model.yes_reset_conditions=True listing=self.t.load_template('utils/list.phtml', simplelist=self, list=list_items, pages=pages, ajax=self.ajax) list_items.close() return listing """ @staticmethod def get_ajax_page(model): pass """ class AjaxList(SimpleList): """Class for make a list from a table based in Ajax """ # Fields example: [['Hostname', True], ['IP', True], ['Options', False]] # arr_order_fields=['server.hostname', 'server.ip'] # 'select count(servercloud.id) as num_elements from servercloud where servercloud.user_id=%s' # params count_query [s['cu_id']] # str_query no order, no limit -> select server.hostname, server.ip, servercloud.id from server, servercloud where server.id=servercloud.server_id and servercloud.user_id=%s # str_query_params -> [s['cu_id'], begin_page, limit] def __init__(self, db, fields, arr_order_fields, count_query, str_query): """Class for make a list from a table based in Ajax A class that is useful for creating listings based on database models using Ajax Args: db (sql connection): A MySQL connection used for get the model. fields (list): A list with the fields showed in table arr_order_fields (list): A list with the sql names of selected fields for show. count_query (str): sql segment for count query sentence. Example: select count(id) from table WHERE name=%s str_query (str): sql segment for query sentence. Example: select id from table WHERE name=%s Attributes: fields (list): A list with the fields showed in table arr_order_fields (list): A list with the sql names of selected fields for show. limit (int): the number of items selected in query sentence. count_query (str): sql segment for count query sentence. Example: select count(id) from table WHERE name=%s count_query_params (list): A list with the params for parse a sql count query with %s symbols (View python help about sql sentences and connectors) str_query (str): sql segment for query sentence. Example: select id from table WHERE name=%s str_query_params (list): A list with the params for parse a sql query with %s symbols (View python help about sql sentences and connectors) initial_num_pages (int): Initial number of pages showed in pagination. db (sql connection): A MySQL connection used for get the model. func_fields (dict): A series of functions used for a series of extra fields referring to each row of the table initial_order_field (str): FIeld used for order the table in first execution initial_order (int): If 0, the initial order is Ascendent, if 1, the initial order is Descendent. """ self.fields=fields self.arr_order_fields=arr_order_fields self.limit=20 self.count_query=count_query[0] self.count_query_params=count_query[1] self.str_query=str_query[0] self.str_query_params=str_query[1] self.initial_num_pages=20 self.db=db self.func_fields={} self.initial_order_field='' self.initial_order=0 def show(self): """Method for show the table The principal method of the class. The list is showed with the selected fields, search form, pagination... """ begin_page=int(get_query_args('position', 0)) order_field=get_query_args('order_field', self.initial_order_field) order=get_query_args('order', self.initial_order) limit=self.limit arr_order=['ASC', 'DESC'] order_sql='' order_params=[] if order_field!='': try: order_field=int(order_field) order=int(order) if order_field>=0 and order_field=0 and order<2: order_sql+=' %s' % arr_order[order] #order_params=[self.arr_order_fields[order_field]] except: order_field=0 order=0 rows=[] with self.db.query(self.count_query, self.count_query_params) as cursor: total_elements=cursor.fetchone()['num_elements'] str_query=self.str_query+' '+order_sql params=self.str_query_params html_pages='' if self.limit>0: str_query+=' limit %s, %s' params.append(begin_page) params.append(limit) pages=Pages() html_pages=_('Pages')+': '+pages.show( begin_page, total_elements, limit, '#' ,initial_num_pages=self.initial_num_pages, variable='begin_page', label='', func_jscript='') with self.db.query(str_query, params) as cursor: for row in cursor: """ c=len(self.arr_order_fields) for x in range(c, len(row)): key_field=list(row.keys())[x] #print(key_field) pass """ for func_field in self.func_fields: if func_field in row: row[func_field]=self.func_fields[func_field](row[func_field], row) rows.append(row) #{k:d[k] for in set(d).intersection(l)} return {'fields': self.fields, 'rows': rows, 'html_pages': html_pages} class SimpleAjaxList(): pass