Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlite backend + some pylint fixes #9

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__pycache__
venv
/.vscode/settings.json
just_any_thing_please_delete_was_pip__pycache__typo
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"python.pythonPath": "/Applications/MAMP/htdocs/pythonGrid/venv/bin/python3"
"python.pythonPath": "/home/gilbert/pythongrid/venv/bin/python"
}
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"**.
Expand Down
17 changes: 11 additions & 6 deletions app/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -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'])
Expand Down Expand Up @@ -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:
Expand Down
71 changes: 37 additions & 34 deletions app/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json, string, re
from app import app
from collections import OrderedDict
import os


class PythonGrid():
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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):

Expand All @@ -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]
Expand Down Expand Up @@ -530,7 +529,7 @@ def display_events(self):
def display_script_begin(self):
script_begin = ''

script_begin += '<script type="text/javascript">' + "\n";
script_begin += '<script type="text/javascript">' + "\n"
script_begin += '//<![CDATA[' + "\n"
script_begin += 'var lastSel;' + "\n"
script_begin += 'var pg_' + self.__jq_gridName + ';' + "\n"
Expand Down Expand Up @@ -618,7 +617,11 @@ def display_toolbar(self):

# resizable grid (beta - jQuery UI)
if self.__jqu_resize['is_resizable']:
toolbar += 'jQuery("#' + self.__jq_gridName + '").jqGrid("gridResize",{minWidth:'. self.__jqu_resize['min_width'] + ',minHeight:' + self.__jqu_resize['min_height'] + '});' + "\n"
toolbar = toolbar + 'jQuery("#' + \
self.__jq_gridName + \
'").jqGrid("gridResize",{minWidth:' + \
self.__jqu_resize['min_width'] + \
',minHeight:' + self.__jqu_resize['min_height'] + '});' + "\n"

# inline search
if self.__has_tbarsearch:
Expand Down Expand Up @@ -702,7 +705,7 @@ def display_script_end(self):

script_end += 'pg_' + self.__jq_gridName + '.jqGrid("destroyFilterToolbar");'
script_end += 'pg_' + self.__jq_gridName + '.jqGrid("filterToolbar",{stringResult: true, searchOnEnter: true, defaultSearch: "cn"});' + "\n"
script_end += 'pg_' + self.__jq_gridName + '[0].triggerToolbar();' + "\n";
script_end += 'pg_' + self.__jq_gridName + '[0].triggerToolbar();' + "\n"


script_end += "\n" + '}); // jQuery(document).ready(function($){ ' + "\n"
Expand Down Expand Up @@ -745,10 +748,10 @@ def display(self):
disp += self.display_properties_end()
#disp += display_extended_properties();
disp += self.display_toolbar()
disp += self.display_before_script_end();
disp += self.display_script_end();
disp += self.display_before_script_end()
disp += self.display_script_end()

disp += self.__display_container();
disp += self.__display_container()

disp += self.display_events()

Expand All @@ -763,7 +766,7 @@ def set_col_title(self, col_name, new_title):

def set_caption(self, capition):
if capition == '':
caption = '&nbsp'
capition = '&nbsp'

self.__jq_caption = capition

Expand All @@ -785,7 +788,7 @@ def set_col_hidden(self, col_name, edithidden=True):
self.__col_hiddens[col]['edithidden'] = edithidden

else:
col_names = re.split("/[\s]*[,][\s]*/", col_name)
col_names = re.split(r"/[\s]*[,][\s]*/", col_name)
for col in col_names:
self.__col_hiddens[col] = OrderedDict()
self.__col_hiddens[col]['edithidden'] = edithidden
Expand Down Expand Up @@ -816,13 +819,13 @@ def set_col_readonly(self, arr):
if isinstance(arr, list):
self.__col_readonly = self.__col_readonly + arr
else:
self.__col_readonly = self.__col_readonly + re.split("/[\s]*[,][\s]*/", arr)
self.__col_readonly = self.__col_readonly + re.split(r"/[\s]*[,][\s]*/", arr)

return self

# TODO - not finished, can't test without finishing EDIT first
def set_col_required(self, arr):
self.__col_required = re.split("/[\s]*[,][\s]*/", arr)
self.__col_required = re.split(r"/[\s]*[,][\s]*/", arr)

'''for col_name in self.__col_required:
$this->cust_col_properties[$col_name] = array("formoptions"=>
Expand Down Expand Up @@ -858,12 +861,12 @@ def add_event(self, event_name, js_event_handler):
return self


'''
"""
* Enable integrated toolbar search
* @param boolean $can_search Enable integrated toolbar search
* @param Array $auto_filter Excel-like auto filter
* @return grid object
'''
"""
def enable_search(self, can_search, auto_filters = []):
self.__has_tbarsearch = can_search
self.__auto_filters = auto_filters
Expand Down
Loading