diff --git a/.gitignore b/.gitignore index 149ee80..5a8fb54 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ venv /.vscode/settings.json +just_any_thing_please_delete_was_pip__pycache__typo diff --git a/.vscode/settings.json b/.vscode/settings.json index 6cf0e5d..e0546ed 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "python.pythonPath": "/Applications/MAMP/htdocs/pythonGrid/venv/bin/python3" + "python.pythonPath": "/home/gilbert/pythongrid/venv/bin/python" } \ No newline at end of file diff --git a/README.md b/README.md index bc6bfb5..a4bd59c 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Within the download you will see something like this: ├── sample │   ├── sampledb_postgres.sql │   ├── sampledb_mysql.sql +│ └── sampledb_sqlite.sql ├── config.py ├── index.py └── requirements.txt @@ -60,9 +61,9 @@ pythonGrid current has two main files in `grid.py` and `data.py` in **app** fold ## Creating the Database -Find the sample database in folder [**sampledb**](https://github.com/pycr/pythongrid/blob/master/app/sample/). Using your favorite MySQL os Postgres client (more database supports are coming). +Find the sample database in folder [**sampledb**](https://github.com/pycr/pythongrid/blob/master/app/sample/). Using your favorite SQLITE, MySQL or Postgres client (more database supports are coming). -1. Create a new database named `sampledb` +1. Create a new database named `sampledb` (`pygrid.db` file for SQLITE to put in the project root (not app)) 2. Run the sample sql script. ## Install Python @@ -132,6 +133,13 @@ For Postgres set database type to `postgres+psycopg2` PYTHONGRID_DB_TYPE = 'postgres+psycopg2' ``` +For SQLITE +```python +PYTONGRID_SQLALCHEMY = 'sqlite:///pygrid.db' +PYTHONGRID_DB_CHARSET = 'utf-8' +PYTHONGRID_DB_TYPE = 'sqlite' +``` + ## Initialize Grid Flask uses *view functions* to handle for the application routes. View functions are mapped to one or more route URLs so that Flask knows what logic to execute when a client requests a given URL such as **"https://example.com/grid"**. diff --git a/app/data.py b/app/data.py index b57791f..eb3b3a1 100644 --- a/app/data.py +++ b/app/data.py @@ -7,12 +7,13 @@ from pprint import pprint import logging from collections import OrderedDict +from flask import current_app as app class PythonGridDbData(): def __init__(self, sql): - self.__gridName = request.args['gn'] if 'gn' in request.args.keys() else sys.exit('PYTHONGRID_ERROR: ULR parameter "gn" is not defined.'); + self.__gridName = request.args['gn'] if 'gn' in request.args.keys() else sys.exit('PYTHONGRID_ERROR: ULR parameter "gn" is not defined.') self.__data_type = request.args['dt'] if 'dt' in request.args.keys() else 'json' self.__grid_sql = sql self.__sql_filter = '' #TODO filter from set_query_filter() @@ -29,8 +30,12 @@ def __init__(self, sql): self.__num_fields = 0 self.__field_names = [] self.__field_types = [] - - engine = sqlalchemy.create_engine(app.config['PYTHONGRID_DB_TYPE']+'://'+app.config['PYTHONGRID_DB_USERNAME']+':'+app.config['PYTHONGRID_DB_PASSWORD']+'@'+app.config['PYTHONGRID_DB_HOSTNAME']+'/'+app.config['PYTHONGRID_DB_NAME']+'?unix_socket='+app.config['PYTHONGRID_DB_SOCKET']).connect() + + if app.config['PYTHONGRID_DB_TYPE'] in ("mysql+pymysql","postgres+psycopg2"): + engine = sqlalchemy.create_engine(app.config['PYTHONGRID_DB_TYPE']+'://'+app.config['PYTHONGRID_DB_USERNAME']+':'+app.config['PYTHONGRID_DB_PASSWORD']+'@'+app.config['PYTHONGRID_DB_HOSTNAME']+'/'+app.config['PYTHONGRID_DB_NAME']+'?unix_socket='+app.config['PYTHONGRID_DB_SOCKET']).connect() + elif app.config['PYTHONGRID_DB_TYPE'] in ("sqlite"): + engine = sqlalchemy.create_engine(app.config['PYTONGRID_SQLALCHEMY']) + md = sqlalchemy.MetaData() table = sqlalchemy.Table(self.__gridName, md, autoload=True, autoload_with=engine) @@ -109,7 +114,7 @@ def __init__(self, sql): not type(fm_type) == sqlalchemy.sql.sqltypes.TEXT and \ not type(fm_type) == sqlalchemy.sql.sqltypes.String: - sqlStrType = 'CHAR' if app.config['PYTHONGRID_DB_TYPE'].find('mysql') != -1 else 'VARCHAR' + sqlStrType = 'CHAR' if app.config['PYTHONGRID_DB_TYPE'] in ('mysql+pymysql', 'sqlite') else 'VARCHAR' sqlWhere += groupOp + " CAST(" + sqlalchemy_utils.functions.quote(engine, rules[i]['field']) + " AS " + sqlStrType + ")" + \ (filter % rules[i]['data']) @@ -147,12 +152,12 @@ def __init__(self, sql): # ****************** prepare the final query *********************** # Store GROUP BY Position - groupBy_Position = sql.upper().find("GROUP BY") + # groupBy_Position = sql.upper().find("GROUP BY") if self.__sql_filter != '' and searchOn : SQL = self.__grid_sql + ' WHERE ' + self.__sql_filter + ' AND (' + sqlWhere + ')' + sqlOrderBy elif self.__sql_filter != '' and not searchOn : - SQL = self.__grid_sql + ' WHERE ' + self.sql_filter + sqlOrderBy + SQL = self.__grid_sql + ' WHERE ' + self.__sql_filter + sqlOrderBy elif self.__sql_filter == '' and searchOn : SQL = self.__grid_sql + ' WHERE ' + sqlWhere + sqlOrderBy else: diff --git a/app/grid.py b/app/grid.py index ec5009d..e3aba3e 100644 --- a/app/grid.py +++ b/app/grid.py @@ -2,6 +2,7 @@ import json, string, re from app import app from collections import OrderedDict +import os class PythonGrid(): @@ -29,8 +30,12 @@ def __init__(self, sql, sql_key='', sql_table='', db_connection=[]): self.pdf_logo = '' # PDF logo property (PDF export and file must be jpg only) self.debug = False # TODO - will be deprecated next version - self.db = create_engine(app.config['PYTHONGRID_DB_TYPE']+'://'+app.config['PYTHONGRID_DB_USERNAME']+':'+app.config['PYTHONGRID_DB_PASSWORD']+'@'+app.config['PYTHONGRID_DB_HOSTNAME']+'/'+app.config['PYTHONGRID_DB_NAME']+'?unix_socket='+app.config['PYTHONGRID_DB_SOCKET'], encoding=app.config['PYTHONGRID_DB_CHARSET']) - + if app.config['PYTHONGRID_DB_TYPE'] in ("mysql+pymysql","postgres+psycopg2"): + self.db = create_engine(app.config['PYTHONGRID_DB_TYPE']+'://'+app.config['PYTHONGRID_DB_USERNAME']+':'+app.config['PYTHONGRID_DB_PASSWORD']+'@'+app.config['PYTHONGRID_DB_HOSTNAME']+'/'+app.config['PYTHONGRID_DB_NAME']+'?unix_socket='+app.config['PYTHONGRID_DB_SOCKET']).connect() + elif app.config['PYTHONGRID_DB_TYPE'] in ("sqlite"): + self.db = create_engine(app.config['PYTONGRID_SQLALCHEMY']) + + self.db_connection = [] self.obj_subgrid = [] # subjgrid object self.obj_md = [] # master detail object @@ -179,8 +184,11 @@ def __init__(self, sql, sql_key='', sql_table='', db_connection=[]): def __del__(self): + pass + """ if self.db.open: self.db.close() + """ def display_script_includeonce(self): @@ -296,14 +304,14 @@ def display_properties_main(self): props += """grid.jqGrid("editRow", id, { focusField: function(){ return((e) ? e.target : null) }, keys:true, - oneditfunc:function(){""" + "\n"; + oneditfunc:function(){""" + "\n" if not self.__col_autocomplete: for col_name in self.__col_autocomplete: props += '$("#' + self.__jq_gridName + ' tr#"+id+" td select[id="+id+"_' + col_name + ']").select2({width:"100%",minimumInputLength:0});' + "\n" # props += $this->get_nested_dropdown_js($col_name); - for key, value in enumerate(self.__col_wysiwyg): + for key in enumerate(self.__col_wysiwyg): props += '$("#"+id+"_' + key + '").wysiwyg({' \ """plugins: { autoload: true, @@ -376,27 +384,18 @@ def display_properties_main(self): def prepare_grid(self): - connection = self.db.raw_connection() - - try: - with connection.cursor() as cursor: - cursor.execute(self.__sql) - result = cursor.fetchall() + with self.db.connect() as connection: + result = connection.execute(self.__sql) - field_names = [i[0] for i in cursor.description] + field_names = [i[0] for i in result.cursor.description] - self.__num_fields = len(cursor.description) - self.__num_rows = 0 + self.__num_fields = len(result.cursor.description) + self.__num_rows = 0 - self.set_colNames(result, field_names) - self.set_colModels(result, cursor.description) - - finally: - pass #connection.close() - - return - + self.set_colNames(result, field_names) + self.set_colModels(result, result.cursor.description) + result.close() def set_colNames(self, result, field_names): @@ -418,7 +417,7 @@ def set_colNames(self, result, field_names): def set_colModels(self, result, meta_data): self.jq_colModel = [] # must reset each time, Flask keeps the list in memory somehow - connection = self.db + # connection = self.db colModel = [] field_names = [i[0] for i in meta_data] @@ -530,7 +529,7 @@ def display_events(self): def display_script_begin(self): script_begin = '' - script_begin += '