Skip to content
Snippets Groups Projects
Commit 3d4b4694 authored by Renaud Le Gac's avatar Renaud Le Gac
Browse files

Improve the documentation.

Modif few method is_blabla_valid --> is_blabla_in_db and modify the code accordingly.
parent bddbf327
No related branches found
No related tags found
No related merge requests found
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
$Id$ $Id$
""" """
__version__ = "$Revision" __version__ = "$Revision$"
#from gluon.html import * #from gluon.html import *
#from gluon.http import * #from gluon.http import *
...@@ -18,20 +18,21 @@ import re ...@@ -18,20 +18,21 @@ import re
from gluon.contrib import simplejson as json from gluon.contrib import simplejson as json
import sqlite3 import sqlite3
RECORD_IS_DELETED = "Record id %i deleted"
FIELD_BAD_SYNTAX = "The syntax of the request field %s is wrong: db.table.field" FIELD_BAD_SYNTAX = "The syntax of the request field '%s' is wrong [db.table.field]"
FIELD_BAD_TABLE = "Table defined in the request field %s doesn't exist." FIELD_BAD_TABLE = "Table defined in the request field '%s' doesn't exist."
FIELD_BAD_FIELD = "Field defined in the request field %s doesn't exist." FIELD_BAD_FIELD = "Field defined in the request field '%s' doesn't exist."
ID_MISSING = "The keyword id is not defined."
INSERT_SUCCESSFUL = "Data insert successfully." KEYWORD_MISSING = "The keyword '%s' is not defined."
SVC_INVALID = "Requested service doesn't exist." SVC_INVALID = "Requested service doesn't exist."
SVC_NOT_DEFINED = "The keyword service is not defined." SVC_NOT_DEFINED = "The keyword service is not defined."
SVC_NOT_IMPLEMENTED = "Service not yet implemented." SVC_NOT_IMPLEMENTED = "Service not yet implemented."
TABLE_NOT_IN_DB = "The request table doesn't exist in the database." TABLE_NOT_IN_DB = "The request table doesn't exist in the database."
TABLE_MISSING = "The keyword table is not defined."
TABLE_FIELD_SAME_TABLE = "Keywords table and field refer to the same table."
TABLE_OR_FIELD_MISSING = "Keyword table or fields is missing"
RECORD_IS_DELETED = "Record is deleted"
RECORD_IS_INSERTED = "Record is inserted with id %i"
class HttpDb: class HttpDb:
""" HttpDb """ HttpDb
...@@ -42,7 +43,7 @@ class HttpDb: ...@@ -42,7 +43,7 @@ class HttpDb:
Handle HTTP POST and HTTP GET request. Handle HTTP POST and HTTP GET request.
The selection of the service and its configuration are based on The selection of the service and its configuration are based on
steering keywords: service, table, fields, debug,... steering keywords: service, table, fields, query, debug,...
The former is mandatory while the laters are optional. The former is mandatory while the laters are optional.
Each service return a dictionary with the the following key: Each service return a dictionary with the the following key:
...@@ -65,7 +66,7 @@ class HttpDb: ...@@ -65,7 +66,7 @@ class HttpDb:
def __init__(self, db): def __init__(self, db):
self._db = db self._db = db
self.__vars = None self._vars = None
def _debug(self): def _debug(self):
"""Return true if the keyword debug is in the request and """Return true if the keyword debug is in the request and
...@@ -75,7 +76,7 @@ class HttpDb: ...@@ -75,7 +76,7 @@ class HttpDb:
return ("debug" in self._vars) and self._vars.debug return ("debug" in self._vars) and self._vars.debug
def _is_field_valid(self, table, field): def _is_field_in_db(self, table, field):
"""Check if the field is defined in the table. """Check if the field is defined in the table.
Return a dictionary with status and message: Return a dictionary with status and message:
...@@ -91,7 +92,8 @@ class HttpDb: ...@@ -91,7 +92,8 @@ class HttpDb:
def _is_field_string_valid(self, field): def _is_field_string_valid(self, field):
"""Check is the request field string is valid. """Check is the request field string is valid.
A well form field string is 'db.table.field' A well form field string is 'db.table.field' or 'db.table.ALL'
The table and the field should exist in the database.
Return a dictionary with status and error message: Return a dictionary with status and error message:
{success: False, msg: 'blalbla'} {success: False, msg: 'blalbla'}
...@@ -102,13 +104,16 @@ class HttpDb: ...@@ -102,13 +104,16 @@ class HttpDb:
if not m: if not m:
return {"success": False, "msg": FIELD_BAD_SYNTAX % field} return {"success": False, "msg": FIELD_BAD_SYNTAX % field}
# Check the table # Check the table is defined in the database
resp = self._is_table_valid(m.group("table")) resp = self._is_table_in_db(m.group("table"))
if not resp["success"]: if not resp["success"]:
return resp return resp
# Check the field # Check the field is defined in the database
return self._is_field_valid(m.group("table"), m.group("field")) if m.group("field") == "ALL":
return {"success": True}
return self._is_field_in_db(m.group("table"), m.group("field"))
def _is_field_value_valid(self, table, field, val): def _is_field_value_valid(self, table, field, val):
...@@ -140,8 +145,8 @@ class HttpDb: ...@@ -140,8 +145,8 @@ class HttpDb:
return {"success": True} return {"success": True}
def _is_table_valid(self, table): def _is_table_in_db(self, table):
"""Check if the request table is valid. """Check if the request table is in the database.
Return a dictionary with status and error message: Return a dictionary with status and error message:
{success: False, msg: 'blalbla'} {success: False, msg: 'blalbla'}
...@@ -168,10 +173,14 @@ class HttpDb: ...@@ -168,10 +173,14 @@ class HttpDb:
def delete(self): def delete(self):
"""Delete data in the database. """Delete a record in the database.
Mandatory steering keywords:
Delete a record identified by its id. query
Mandatory steering keywords are: service, table and id. string identifying the record to be deleted
i.e "db.table.id==10".
Equivalent of the SQL directive where.
Return a dictionary with status and error message: Return a dictionary with status and error message:
{success: False, msg: 'blalbla'} {success: False, msg: 'blalbla'}
...@@ -180,26 +189,16 @@ class HttpDb: ...@@ -180,26 +189,16 @@ class HttpDb:
if self._debug(): if self._debug():
print "Start HttpDb.debug service." print "Start HttpDb.debug service."
# Check table if "query" not in self._vars:
if "table" not in self._vars: resp = {"success": False, "msg": KEYWORD_MISSING % "query"}
resp = {"success": False, "msg": TABLE_MISSING}
return resp
# Check id
if "id" not in self._vars:
resp = {"success": False, "msg": ID_MISSING}
return resp return resp
# Delete the record
id = int(self._vars.id)
table = self._vars.table
try: try:
del self._db[table][id] self._db(self._mapdb(self._vars.query)).delete()
except sqlite3.Error, e: except sqlite3.Error, e:
return {"success": False, "msg": e.message} return {"success": False, "msg": e.message}
return {"success": True, "msg": RECORD_IS_DELETED % id} return {"success": True, "msg": RECORD_IS_DELETED}
def get_defaults(self): pass def get_defaults(self): pass
def get_fields(self): pass def get_fields(self): pass
...@@ -208,20 +207,30 @@ class HttpDb: ...@@ -208,20 +207,30 @@ class HttpDb:
def insert(self): def insert(self):
"""Insert data in the database. """Insert a record in the database.
Thsi service is strongly linked to a Ext.FormPanel widget.
This service is strongly linked to a Ext.FormPanel widget.
Form sent field values via a JSON string containing the steering Form sent field values via a JSON string containing the steering
keywords table and field names. The field name is the simplest keywords:
version which doesn't contains the dabatase model and the table:
version instead of db.distributions.version. debug
boolean
table
the table name where data will be inserted.
field1, field2,...
the field value.
The field name is the simplest version which doesn't
contains the dabatase model and the table:
i.e version instead of db.distributions.version.
Return a dictionary with status, error message and id of the insert row: Return a dictionary with status, error message and id of the insert row:
{success: False, msg: 'blalbla', errors: {field: 'blabla',..}, data:{id:xx}} {success: False, msg: 'blalbla', errors: {field: 'blabla',..}, data:{id:xx}}
The keyword success is mandatory. The keyword success is mandatory.
The keyword error is required and processed by the Ext.FormPanel widget. The keyword error is processed by the Ext.FormPanel widget.
""" """
if self._debug(): if self._debug():
...@@ -229,12 +238,12 @@ class HttpDb: ...@@ -229,12 +238,12 @@ class HttpDb:
# Check table # Check table
if "table" not in self._vars: if "table" not in self._vars:
resp = {"success": False, "msg": TABLE_MISSING} resp = {"success": False, "msg": KEYWORD_MISSING % "table"}
return resp return resp
table = self._vars.table table = self._vars.table
resp = self._is_table_valid(table) resp = self._is_table_in_db(table)
if not resp["success"]: if not resp["success"]:
return resp return resp
...@@ -246,12 +255,13 @@ class HttpDb: ...@@ -246,12 +255,13 @@ class HttpDb:
# Check that fields exits in the selected table # Check that fields exits in the selected table
for field in kwfields: for field in kwfields:
resp = self._is_field_valid(table, field) resp = self._is_field_in_db(table, field)
if not resp["success"]: if not resp["success"]:
return resp return resp
# Validate field values against model validators # Validate field values against model validators
# Check all fields in one go # Check all fields in one go
# Propagate errors to the UI
resp = {"success": True, "errors": {}} resp = {"success": True, "errors": {}}
for (field, val) in kwfields.items(): for (field, val) in kwfields.items():
di = self._is_field_value_valid(table, field, val) di = self._is_field_value_valid(table, field, val)
...@@ -271,11 +281,13 @@ class HttpDb: ...@@ -271,11 +281,13 @@ class HttpDb:
if self._debug(): if self._debug():
print "End HttpDb.insert service." print "End HttpDb.insert service."
return {"success": True, "msg": INSERT_SUCCESSFUL, "data": {"id": id}} return {"success": True,\
"msg": RECORD_IS_INSERTED % id,\
"data": {"id": id}}
def proceed(self, vars): def proceed(self, vars):
"""Proceed the data sends via the POST/GET method. """Proceed the request sends via the POST/GET method.
the input vars is a Storage object. the input vars is a Storage object.
...@@ -298,32 +310,26 @@ class HttpDb: ...@@ -298,32 +310,26 @@ class HttpDb:
def select(self): def select(self):
"""Select data in the database. """Select records in the database.
The steering keywords are:
table Steering keywords are:
A string
When defined, all columns of the table are selected.
fields fields
A list of string ['db.table.field1', db.table.field2,...] A list of string ['db.table1.ALL', db.table2.field3,...]
When defined, specific columns are added.
Both table and fields keywords can be used at the same time,
but can't refer to the same table.
where groupby, orderby
A string: "(db.table.id==1) and db.table2.field4=='foo')"
The equivalent or the SQL where directive.
orderby, orderby
A string: "db.table.field1" A string: "db.table.field1"
The equivalent or the SQL where directive. The equivalent or the SQL directive groupby, orderby.
query
A string: "(db.table.id==1) and (db.table2.field4=='foo')"
The equivalent of the SQL directive where.
having having
left
limitby limitby
A string: "(0,10)" A string: "(0,10)"
The equivalent or the SQL where directive. The equivalent of the SQL directive limitby.
debug debug
A boolean A boolean
...@@ -332,51 +338,37 @@ class HttpDb: ...@@ -332,51 +338,37 @@ class HttpDb:
and the construction of the query, orderby, ... directives. and the construction of the query, orderby, ... directives.
Return a dictionary with selected data, status and error message: Return a dictionary with selected data, status and error message:
{success: false, msg: 'blabla', data: []} {success: false, msg: 'blabla', data: [{field1: xxx,..},...]}
""" """
if self._debug(): if self._debug():
print "Start HttpDb.select service." print "Start HttpDb.select service."
if ("table" not in self._vars) and ("fields" not in self._vars): if "fields" not in self._vars:
resp = {"success": False, "msg": TABLE_OR_FIELD_MISSING} resp = {"success": False, "msg": KEYWORD_MISSING % "fields"}
return resp return resp
if ("table" in self._vars) and ("fields" in self._vars): # The json process sends a string
table = self._vars.table # when only one field is defined
for field in self._vars.fields: fields = self._vars.fields
if table in field: if isinstance(fields, str):
resp = {"success": False, "msg": TABLE_FIELD_SAME_TABLE} fields = [self._vars.fields]
return resp
args, kwargs, query = list(), dict(), list() args, kwargs, query = list(), dict(), list()
# Select all fields of a table for field in fields:
if "table" in self._vars: resp = self._is_field_string_valid(field)
table = self._vars.table
resp = self._is_table_valid(table)
if not resp["success"]: if not resp["success"]:
return resp return resp
args.append(self._db[table].ALL) args.append(self._mapdb(field))
# Add dedicated fields
if "fields" in self._vars:
for field in self._vars.fields:
resp = self._is_field_string_valid(field)
if not resp["success"]:
return resp
args.append(self._mapdb(field))
# Add directive orderby, groupby,...
for key in ["groupby", "having", "left", "limitby", "orderby"]: for key in ["groupby", "having", "left", "limitby", "orderby"]:
if key in self._vars: if key in self._vars and self._vars.key:
kwargs[key] = self._mapdb(self._vars[key]) kwargs[key] = self._mapdb(self._vars[key])
# Decode the where directive if "query" in self._vars and self._vars.query:
if "where" in self._vars: query.append(self._mapdb(self._vars.query))
query.append(self._mapdb(self._vars.where))
# Proceed
if self._debug(): if self._debug():
print "HttpDb.select proceed request:", query, args, kwargs print "HttpDb.select proceed request:", query, args, kwargs
...@@ -391,7 +383,7 @@ class HttpDb: ...@@ -391,7 +383,7 @@ class HttpDb:
def update(self): def update(self):
"""Update data in the database. """Update a record in the database.
Return a dictionary with selected status and error message: Return a dictionary with selected status and error message:
{success: false, msg: 'blalbla'} {success: false, msg: 'blalbla'}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment