More docs in webmodel

This commit is contained in:
Antonio de la Rosa 2022-05-05 22:31:44 +02:00
parent 1281e385a8
commit fced4d5756

View file

@ -342,8 +342,16 @@ class WebModel:
related_models_deleted (list): Internal variable used for delete tables from db. related_models_deleted (list): Internal variable used for delete tables from db.
required_save (str): Internal variable used for required fields defined in self.fields required_save (str): Internal variable used for required fields defined in self.fields
primary_key (str): Default name of primary key field primary_key (str): Default name of primary key field
yes_reset_conditions (bool): yes_reset_conditions (bool): If True, methods how select and update reset self.conditions. If False, self.conditions is used in next select and update executions.
updated (bool): True if the model is used for update, False if the model is used for insert or other operations.
valid_fields (list): List with the fields validated for insert or update
last_id (int): The id of last inserted row.
distinct (str): Add DISTINCT keyword to self.select method.
post (dict): A simple dictionary where post values are saved for use of fields classes
files_delete (dict): A simple dictionary that save the fields that have files related. If i delete the row in database i need delete the files related
sql_class (SqlClass): A sql_class used for connect to db.
show_formatted (bool): If True, by default all fields are showed with formatted value using show_formatted method of PhangoField classes and children in select method. If False, raw value is showed.
enctype (bool): If True, forms generated using this model are prepared for enctype=multipart/form-data A.K.A. upload files.
""" """
self.cached=WebModel.global_cached self.cached=WebModel.global_cached
@ -453,7 +461,11 @@ class WebModel:
# A method for add the connection # A method for add the connection
def conn(self, sqlclass): def conn(self, sqlclass):
""" Method for get the SqlClass object and prepare sql variables
Args:
sqlclass (SqlClass): A SqlClass object that present the db connection
"""
self.sqlclass=sqlclass self.sqlclass=sqlclass
# Reset conditions # Reset conditions
@ -469,6 +481,11 @@ class WebModel:
# A method for change the name of table # A method for change the name of table
def change_name(self, name): def change_name(self, name):
""" A method for change the name of table
Args;
name (str): The new name of table
"""
self.name=name self.name=name
@ -477,6 +494,7 @@ class WebModel:
# A method where create the new fields of this model # A method where create the new fields of this model
def create_fields(self): def create_fields(self):
"""Dummy method for use in children classes for add fields"""
#print([i for i in dir(self.__class__) if i[:1] != '_']) #print([i for i in dir(self.__class__) if i[:1] != '_'])
#print(dir(self)) #print(dir(self))
@ -486,6 +504,14 @@ class WebModel:
# A method for register the fields # A method for register the fields
def register(self, field_model, required=False): def register(self, field_model, required=False):
"""A method for register the fields in model class
With this method, your register your fields in the model, inside self.fields attribute. Fields are used for build the query for get the data from the sql table.
Args:
field_model (PhangoField): PhangoField object for add to model
required (bool): If True, the field is required when you insert or update a item row in table model. If False, the field is not required. If field is not required and checking fail, the model update/insert ignore it.
"""
#self.fields_required[field_model]=field_model.required #self.fields_required[field_model]=field_model.required
@ -527,6 +553,13 @@ class WebModel:
# Method for make queries # Method for make queries
def query(self, str_query, args=[], connection_id='default'): def query(self, str_query, args=[], connection_id='default'):
"""Method for make typical sql query to db
Args:
str_query (str): The str query. Use the typical format of sql python drivers, example: select * from my_table WHERE id=%s.
args (list): The arguments to substitute %s characters of the strings. The list must sequential with %s characters in the string.
connection_id (str): The connection data used for this connection, by default is "default".
"""
self.connect_to_db() self.connect_to_db()
return self.sqlclass.query(str_query, args, connection_id) return self.sqlclass.query(str_query, args, connection_id)
@ -534,6 +567,8 @@ class WebModel:
# Method for clean fields # Method for clean fields
def clean_fields(self): def clean_fields(self):
"""Method for delete fields from self.fields dict"""
clean=self.fields_to_clean clean=self.fields_to_clean
for field in self.fields_to_clean: for field in self.fields_to_clean:
del self.fields[field] del self.fields[field]
@ -542,6 +577,14 @@ class WebModel:
# External agent define if the update is in code or from external source, how a form. # External agent define if the update is in code or from external source, how a form.
def insert(self, dict_values, external_agent=True): def insert(self, dict_values, external_agent=True):
"""Insert method, for insert a row in database using a dictionary
This method is a shortcut for typical sql insert sentence.
Args:
dict_values (dict): A dict with the name of the fields how defined in PhangoField for the keys, and values for the values designed for every field.
external_agent (bool): External agent define if the update is in code or from external source, how a form.
"""
self.clean_fields() self.clean_fields()
@ -598,6 +641,15 @@ class WebModel:
# Update method. For update one or many rows. # Update method. For update one or many rows.
def update(self, dict_values, external_agent=True): def update(self, dict_values, external_agent=True):
"""Upate method, for update a row in database using a dictionary
This method is a shortcut for typical sql update sentence.
Args:
dict_values (dict): A dict with the name of the fields how defined in PhangoField for the keys, and values for the values designed for every field.
external_agent (bool): External agent define if the update is in code or from external source, how a form.
"""
self.clean_fields() self.clean_fields()
@ -672,7 +724,7 @@ class WebModel:
""" """
def reset_conditions(self): def reset_conditions(self):
"""Method for reset self.conditions to default values"""
self.conditions=["WHERE 1=1", []] self.conditions=["WHERE 1=1", []]
self.limit='' self.limit=''
@ -680,6 +732,18 @@ class WebModel:
#Type assoc can be assoc for return dictionaries #Type assoc can be assoc for return dictionaries
def select(self, arr_select=[], raw_query=False): def select(self, arr_select=[], raw_query=False):
"""A method for select fields from a table in db. Support for foreignkeys.
This method is a shortcut for typical sql select sentence. You can select multiple tables using ForeignKeyField class.
Args:
arr_select (dict): A list with the name of the fields how defined in PhangoField.
raw_query (bool): If True, if foreignkeyfields exists, are not selected. If False, foreignkeyfields are selected too if foreignkeyfield are in arr_select.
Returns:
Return cursor db for get data using loops or other if operation is successful, if not, return False.
"""
self.clean_fields() self.clean_fields()
@ -795,14 +859,29 @@ class WebModel:
# Show results in a dictionary # Show results in a dictionary
def fetch(self, cursor): def fetch(self, cursor):
""" Simple method for get a row from db using cursor
Args:
cursor (Db cursor): A typical db cursor of python sql interface standard.
Returns:
dict: Return a dictionary with the row selected.
"""
return cursor.fetchone() return cursor.fetchone()
def insert_id(self): def insert_id(self):
"""Method for get the id from last row inserted in table"""
return self.last_id return self.last_id
def element_exists(self, id): def element_exists(self, id):
"""Check if exist row with id in db
Args:
id (int): The id of the row to search.
"""
self.conditions=['WHERE `'+self.name_field_id+'`=%s', [id]] self.conditions=['WHERE `'+self.name_field_id+'`=%s', [id]]
@ -820,6 +899,15 @@ class WebModel:
pass pass
def select_a_row(self, id, fields_selected=[], raw_query=0): def select_a_row(self, id, fields_selected=[], raw_query=0):
"""Shortcut for get a simple row from a query
Args:
fields_selected (dict): A list with the name of the fields how defined in PhangoField.
raw_query (bool): If True, if foreignkeyfields exists, are not selected. If False, foreignkeyfields are selected too if foreignkeyfield are in arr_select.
Returns:
dict: Returns dict with the row values.
"""
self.conditions=['WHERE `'+self.name+'`.`'+self.name_field_id+'`=%s', [id]] self.conditions=['WHERE `'+self.name+'`.`'+self.name_field_id+'`=%s', [id]]
@ -841,6 +929,15 @@ class WebModel:
return row return row
def select_a_row_where(self, fields_selected=[], raw_query=0, begin=0): def select_a_row_where(self, fields_selected=[], raw_query=0, begin=0):
"""Shortcut for get a simple row from a query using self.conditions
Args:
fields_selected (dict): A list with the name of the fields how defined in PhangoField.
raw_query (bool): If True, if foreignkeyfields exists, are not selected. If False, foreignkeyfields are selected too if foreignkeyfield are in arr_select.
Returns:
dict: Returns dict with the row values.
"""
self.limit="limit "+str(begin)+", 1" self.limit="limit "+str(begin)+", 1"
@ -859,6 +956,16 @@ class WebModel:
def select_to_array(self, fields_selected=[], raw_query=0): def select_to_array(self, fields_selected=[], raw_query=0):
"""Shortcut for get a a list of rows from select sql query
Args:
fields_selected (dict): A list with the name of the fields how defined in PhangoField.
raw_query (bool): If True, if foreignkeyfields exists, are not selected. If False, foreignkeyfields are selected too if foreignkeyfield are in arr_select.
Returns:
dict: Returns dict with the row values.
"""
if len(fields_selected)==0: if len(fields_selected)==0:
fields_selected=list(self.fields.keys()) fields_selected=list(self.fields.keys())
@ -899,6 +1006,16 @@ class WebModel:
def select_to_dict(self, fields_selected=[], raw_query=0, integer=True): def select_to_dict(self, fields_selected=[], raw_query=0, integer=True):
"""Shortcut for get a dict of rows from select sql query
Args:
fields_selected (dict): A list with the name of the fields how defined in PhangoField.
raw_query (bool): If True, if foreignkeyfields exists, are not selected. If False, foreignkeyfields are selected too if foreignkeyfield are in arr_select.
Returns:
dict: Returns dict with the row values.
"""
if integer: if integer:
def check_index(index): def check_index(index):
return index return index
@ -944,6 +1061,16 @@ class WebModel:
# A method por count num rows affected for sql conditions # A method por count num rows affected for sql conditions
def select_count(self, field_to_count='id', raw_query=True): def select_count(self, field_to_count='id', raw_query=True):
"""Method for get a typical sql count using conditions
Args:
Args:
fields_selected (dict): A list with the name of the fields how defined in PhangoField.
raw_query (bool): If True, if foreignkeyfields exists, are not selected. If False, foreignkeyfields are selected too if foreignkeyfield are in arr_select.
Returns:
int: Returns the number of elements selected.
"""
# Connect to db # Connect to db
@ -990,6 +1117,11 @@ class WebModel:
# A method for delete rows using sql conditions # A method for delete rows using sql conditions
def delete(self): def delete(self):
"""Method for delete a series of rows using conditions
Returns:
bool: If delete is successfully, return True, if not, return False.
"""
#self.connect_to_db() #self.connect_to_db()
@ -1012,6 +1144,15 @@ class WebModel:
return False return False
def set_conditions(self, sql_text, values:list) -> object: def set_conditions(self, sql_text, values:list) -> object:
"""Method for set conditions for a typical sql query
Args:
sql_text (str): The sql text with the conditions, Example: WHERE id=%s
values (list): A list with values for substitute %s characters for the real values filtered for not allow sql injections.
Returns:
Return the same object with self.conditions modified.
"""
self.conditions=[sql_text, values] self.conditions=[sql_text, values]
@ -1019,6 +1160,15 @@ class WebModel:
@staticmethod @staticmethod
def check_in_list(in_list): def check_in_list(in_list):
"""Method for convert values to int for use in IN (1,2,3) sql sentences.
Args:
in_list (list): List with numbers items.
Returns:
string with (1,2,3) sql sentence filtered.
"""
for x in range(0, len(in_list)): for x in range(0, len(in_list)):
try: try:
@ -1028,6 +1178,15 @@ class WebModel:
return '('+', '.join(in_list)+')' return '('+', '.join(in_list)+')'
def check_in_list_str(self, field, in_list): def check_in_list_str(self, field, in_list):
"""Method for convert values to int for use in IN (value1, value2, value3) sql sentences.
Args:
field (PhangoField): The PhangoField used for check the values of in_list
in_list (list): List with value items.
Returns:
string with (value1, value2, value3) sql sentence filtered.
"""
for x in range(0, len(in_list)): for x in range(0, len(in_list)):
in_list[x]=str(self.fields[field].check(in_list[x])) in_list[x]=str(self.fields[field].check(in_list[x]))
@ -1035,6 +1194,15 @@ class WebModel:
return '("'+'", "'.join(in_list)+'")' return '("'+'", "'.join(in_list)+'")'
def set_order(self, order:dict) -> object: def set_order(self, order:dict) -> object:
""" Method for set and complete the query with "order by" sentences.
Args:
order (dict): A dict with a field name how key, and 0 or 1 how values. 0 define order how ASC, 1 define order how DESC.
Returns:
Returns the same object for execute a query after set_order declaration.
"""
arr_order=[] arr_order=[]
arr_order.append('ASC') arr_order.append('ASC')
@ -1053,6 +1221,15 @@ class WebModel:
return self return self
def set_limit(self, limit: tuple) -> None: def set_limit(self, limit: tuple) -> None:
""" Method for set and complete the query with "limit" sentences.
Args:
limit (tuple): A tuple with one or two elements. If one element, example (1), the result is "LIMIT first_element", if two elements, example (1,2), the result is "LIMIT first_element, two_element"
Returns:
Returns the same object for execute a query after set_order declaration.
"""
limit[0]=int(limit[0]) limit[0]=int(limit[0])
@ -1068,6 +1245,7 @@ class WebModel:
# Method for create sql tables # Method for create sql tables
def create_table(self): def create_table(self):
"""Method for create a table from this model object"""
#self.connect_to_db() #self.connect_to_db()
@ -1178,6 +1356,12 @@ class WebModel:
# Method for drop sql tables and related # Method for drop sql tables and related
def drop(self): def drop(self):
"""Method for drop a table based in this model
Returns:
Return True if table was dropped successfully, false if table can't be dropped.
"""
return self.query('DROP TABLE '+self.name, [], self.connection_id) return self.query('DROP TABLE '+self.name, [], self.connection_id)
#Return an array with all fields #Return an array with all fields
@ -1195,6 +1379,10 @@ class WebModel:
external_agent (bool): If True, the query is considered manipulated by external agent and the checks are stricts, if not, checks are not stricts external_agent (bool): If True, the query is considered manipulated by external agent and the checks are stricts, if not, checks are not stricts
yes_update (bool): If True, the check need be done for update sql sentence, if False, the check is done for insert sql sentence yes_update (bool): If True, the check need be done for update sql sentence, if False, the check is done for insert sql sentence
errors_set (str): If insert value, the errors are set for insert sql statement, if update value, then the errors are set for update sql statement. errors_set (str): If insert value, the errors are set for insert sql statement, if update value, then the errors are set for update sql statement.
Returns:
Return False if checking is wrong. If not False returns a tuple with fields filtered, original values as values and values filtered how update_values
return (fields, values, update_values)
""" """
fields=[] fields=[]
@ -1324,6 +1512,7 @@ class WebModel:
#Reset the require field in fields #Reset the require field in fields
def reset_require(self): def reset_require(self):
"""Reset the require attribute in fields"""
for k, v in self.fields.items(): for k, v in self.fields.items():
@ -1334,6 +1523,7 @@ class WebModel:
#Reload the require field in fields #Reload the require field in fields
def reload_require(self): def reload_require(self):
"""Reload the require field in fields"""
for k,r in self.fields.items(): for k,r in self.fields.items():
self.fields[k].required=r self.fields[k].required=r
@ -1341,6 +1531,7 @@ class WebModel:
#Choose all fields to updated #Choose all fields to updated
def set_valid_fields(self, fields={}): def set_valid_fields(self, fields={}):
"""Choose all fields to updated"""
if len(fields)==0: if len(fields)==0:
fields=self.fields.keys() fields=self.fields.keys()
@ -1350,6 +1541,7 @@ class WebModel:
#Create a form based in table. #Create a form based in table.
def create_forms(self, arr_fields=[]): def create_forms(self, arr_fields=[]):
"""Create a form based in table."""
self.forms=OrderedDict() self.forms=OrderedDict()
@ -1367,6 +1559,12 @@ class WebModel:
return arr_fields return arr_fields
def create_form_after(self, form_after, new_form): def create_form_after(self, form_after, new_form):
"""Create form after other form
Args:
form_after (str): The name of the form where the new form is located next
new_form (BaseForm): The BaseForm or derivated class used for create the new form.
"""
new_dict=OrderedDict() new_dict=OrderedDict()
@ -1378,6 +1576,11 @@ class WebModel:
self.forms=new_dict self.forms=new_dict
def show_errors(self): def show_errors(self):
"""Get all errors of model last operation.
Returns:
str: A string with all errors.
"""
arr_error=[] arr_error=[]
error_txt='' error_txt=''
@ -1398,6 +1601,11 @@ class WebModel:
return error_txt return error_txt
def collect_errors(self): def collect_errors(self):
"""Get all errors and save in dictionary
Returns:
dict: Return a dict where the key is the field where the error exists and value is the error text.
"""
arr_error= {} arr_error= {}
error_txt='' error_txt=''
@ -1415,12 +1623,15 @@ class WebModel:
return arr_error return arr_error
def safe_query(self): def safe_query(self):
"""Method for reset require for fields.
With this method you can make queries without real checks, except mysql injection safe variables."""
self.create_forms() self.create_forms()
self.reset_require() self.reset_require()
def close(self): def close(self):
"""Method for close sqlclass db connection"""
self.sqlclass.close() self.sqlclass.close()
@ -1438,6 +1649,7 @@ class WebModel:
#del sqlclass.connection[key] #del sqlclass.connection[key]
@staticmethod @staticmethod
def escape_sql(value): def escape_sql(value):
"""Manual escape for sql, you shouldn't use it"""
value=str(value) value=str(value)
@ -1451,6 +1663,11 @@ class WebModel:
# Set post values from a post array # Set post values from a post array
def set_post_values(self, post): def set_post_values(self, post):
"""Prepare a dict with values using fields keys how base
Returns:
dict: Return a dict with values without checking anything.
"""
for k in self.fields.keys(): for k in self.fields.keys():