From 3292f760ca7255c878ed84470898c5893d53b23f Mon Sep 17 00:00:00 2001 From: geomapdev Date: Thu, 20 Apr 2017 10:21:16 -0700 Subject: [PATCH 1/6] handle reference fields for keyed tables --- gluon/dal.py | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index 95476a9f..e60cf82d 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -51,11 +51,29 @@ def _default_validators(db, field): if hasattr(referenced, '_format') and referenced._format: requires = validators.IS_IN_DB(db, referenced._id, referenced._format) - if field.unique: - requires._and = validators.IS_NOT_IN_DB(db, field) - if field.tablename == field_type[10:]: - return validators.IS_EMPTY_OR(requires) - return requires + else: + requires = validators.IS_IN_DB(db, referenced._id) + if field.unique: + requires._and = validators.IS_NOT_IN_DB(db, field) + if field.tablename == field_type[10:]: + return validators.IS_EMPTY_OR(requires) + return requires + elif db and field_type.startswith('reference') and \ + field_type.find('.') > 0 and \ + field_type[10:].split('.')[0] in db.tables: + table_name=field_type[10:].split('.')[0] + field_name=field_type[10:].split('.')[1] + referenced = db[table_name] + if hasattr(referenced, '_format') and referenced._format: + requires = validators.IS_IN_DB(db, referenced[field_name], + referenced._format) + else: + requires = validators.IS_IN_DB(db, referenced[field_name]) + if field.unique: + requires._and = validators.IS_NOT_IN_DB(db, field) + if field.tablename == table_name: + return validators.IS_EMPTY_OR(requires) + return requires elif db and field_type.startswith('list:reference') and \ field_type.find('.') < 0 and \ field_type[15:] in db.tables: @@ -71,6 +89,23 @@ def _default_validators(db, field): if not field.notnull: requires = validators.IS_EMPTY_OR(requires) return requires + elif db and field_type.startswith('list:reference') and \ + field_type.find('.') > 0 and \ + field_type[15:].split('.')[0] in db.tables: + table_name=field_type[15:].split('.')[0] + field_name=field_type[15:].split('.')[1] + referenced = db[table_name] + if hasattr(referenced, '_format') and referenced._format: + requires = validators.IS_IN_DB(db, referenced[field_name], + referenced._format, multiple=True) + else: + requires = validators.IS_IN_DB(db, referenced[field_name], + multiple=True) + if field.unique: + requires._and = validators.IS_NOT_IN_DB(db, field) + if not field.notnull: + requires = validators.IS_EMPTY_OR(requires) + return requires # does not get here for reference and list:reference if field.unique: requires.insert(0, validators.IS_NOT_IN_DB(db, field)) From 69e6e79e232db922b0ae4514a6820ee5d2dcf9bb Mon Sep 17 00:00:00 2001 From: geomapdev Date: Mon, 1 May 2017 08:39:31 -0700 Subject: [PATCH 2/6] Update dal.py updated to handle references without format --- gluon/dal.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index 95476a9f..27195f1a 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -51,11 +51,13 @@ def _default_validators(db, field): if hasattr(referenced, '_format') and referenced._format: requires = validators.IS_IN_DB(db, referenced._id, referenced._format) - if field.unique: - requires._and = validators.IS_NOT_IN_DB(db, field) - if field.tablename == field_type[10:]: - return validators.IS_EMPTY_OR(requires) - return requires + else: + requires = validators.IS_IN_DB(db, referenced._id) + if field.unique: + requires._and = validators.IS_NOT_IN_DB(db, field) + if not field.notnull: + return validators.IS_EMPTY_OR(requires) + return requires elif db and field_type.startswith('list:reference') and \ field_type.find('.') < 0 and \ field_type[15:] in db.tables: From 8590aae2e8f5d49f7661afe62b8ad151e054b3c5 Mon Sep 17 00:00:00 2001 From: geomapdev Date: Wed, 4 Oct 2017 10:34:48 -0700 Subject: [PATCH 3/6] dal.py code cleanup --- gluon/dal.py | 92 ++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index e60cf82d..e4abd6fa 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -44,66 +44,50 @@ def _default_validators(db, field): requires.append(validators.IS_TIME()) elif field_type == 'datetime': requires.append(validators.IS_DATETIME()) - elif db and field_type.startswith('reference') and \ - field_type.find('.') < 0 and \ - field_type[10:] in db.tables: - referenced = db[field_type[10:]] - if hasattr(referenced, '_format') and referenced._format: - requires = validators.IS_IN_DB(db, referenced._id, - referenced._format) - else: - requires = validators.IS_IN_DB(db, referenced._id) - if field.unique: - requires._and = validators.IS_NOT_IN_DB(db, field) - if field.tablename == field_type[10:]: - return validators.IS_EMPTY_OR(requires) - return requires - elif db and field_type.startswith('reference') and \ - field_type.find('.') > 0 and \ - field_type[10:].split('.')[0] in db.tables: - table_name=field_type[10:].split('.')[0] - field_name=field_type[10:].split('.')[1] - referenced = db[table_name] - if hasattr(referenced, '_format') and referenced._format: - requires = validators.IS_IN_DB(db, referenced[field_name], - referenced._format) - else: - requires = validators.IS_IN_DB(db, referenced[field_name]) - if field.unique: - requires._and = validators.IS_NOT_IN_DB(db, field) - if field.tablename == table_name: - return validators.IS_EMPTY_OR(requires) - return requires - elif db and field_type.startswith('list:reference') and \ - field_type.find('.') < 0 and \ - field_type[15:] in db.tables: - referenced = db[field_type[15:]] - if hasattr(referenced, '_format') and referenced._format: - requires = validators.IS_IN_DB(db, referenced._id, - referenced._format, multiple=True) - else: - requires = validators.IS_IN_DB(db, referenced._id, - multiple=True) + elif db and field_type.startswith('reference'): + if field_type.find('.') < 0 and field_type[10:] in db.tables: + referenced = db[field_type[10:]] + if hasattr(referenced, '_format') and referenced._format: + requires = validators.IS_IN_DB(db, referenced._id,referenced._format) + else: + requires = validators.IS_IN_DB(db, referenced._id) + elif field_type.find('.') > 0 and field_type[10:].split('.')[0] in db.tables: + table_field = field_type[10:].split('.') + table_name=table_field[0] + field_name=table_field[1] + referenced = db[table_name] + if hasattr(referenced, '_format') and referenced._format: + requires = validators.IS_IN_DB(db, referenced[field_name],referenced._format) + else: + requires = validators.IS_IN_DB(db, referenced[field_name]) if field.unique: requires._and = validators.IS_NOT_IN_DB(db, field) if not field.notnull: - requires = validators.IS_EMPTY_OR(requires) + return validators.IS_EMPTY_OR(requires) return requires - elif db and field_type.startswith('list:reference') and \ - field_type.find('.') > 0 and \ - field_type[15:].split('.')[0] in db.tables: - table_name=field_type[15:].split('.')[0] - field_name=field_type[15:].split('.')[1] - referenced = db[table_name] - if hasattr(referenced, '_format') and referenced._format: - requires = validators.IS_IN_DB(db, referenced[field_name], - referenced._format, multiple=True) - else: - requires = validators.IS_IN_DB(db, referenced[field_name], - multiple=True) + elif db and field_type.startswith('list:reference'): + if field_type.find('.') < 0 and field_type[15:] in db.tables: + referenced = db[field_type[15:]] + if hasattr(referenced, '_format') and referenced._format: + requires = validators.IS_IN_DB(db, referenced._id, + referenced._format, multiple=True) + else: + requires = validators.IS_IN_DB(db, referenced._id, + multiple=True) + elif field_type.find('.') > 0 and field_type[15:].split('.')[0] in db.tables: + table_field = field_type[15:].split('.') + table_name=table_field[0] + field_name=table_field[1] + referenced = db[table_name] + if hasattr(referenced, '_format') and referenced._format: + requires = validators.IS_IN_DB(db, referenced[field_name], + referenced._format, multiple=True) + else: + requires = validators.IS_IN_DB(db, referenced[field_name], + multiple=True) if field.unique: requires._and = validators.IS_NOT_IN_DB(db, field) - if not field.notnull: + if field.notnull: requires = validators.IS_EMPTY_OR(requires) return requires # does not get here for reference and list:reference From 603cc7092a2a490c7d9ae521e92e1f15a2cccc68 Mon Sep 17 00:00:00 2001 From: geomapdev Date: Wed, 4 Oct 2017 10:39:42 -0700 Subject: [PATCH 4/6] dal.py more code cleanup --- gluon/dal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index e4abd6fa..b0e095c5 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -63,7 +63,7 @@ def _default_validators(db, field): if field.unique: requires._and = validators.IS_NOT_IN_DB(db, field) if not field.notnull: - return validators.IS_EMPTY_OR(requires) + requires = validators.IS_EMPTY_OR(requires) return requires elif db and field_type.startswith('list:reference'): if field_type.find('.') < 0 and field_type[15:] in db.tables: @@ -87,7 +87,7 @@ def _default_validators(db, field): multiple=True) if field.unique: requires._and = validators.IS_NOT_IN_DB(db, field) - if field.notnull: + if not field.notnull: requires = validators.IS_EMPTY_OR(requires) return requires # does not get here for reference and list:reference From 02c32ebace87e550a3239bf3f4ac76afa7f1c8ef Mon Sep 17 00:00:00 2001 From: geomapdev Date: Mon, 9 Oct 2017 11:22:48 -0700 Subject: [PATCH 5/6] update gluon unittest for dal reference fields --- gluon/tests/test_validators.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/gluon/tests/test_validators.py b/gluon/tests/test_validators.py index 502b193d..e6cffc54 100644 --- a/gluon/tests/test_validators.py +++ b/gluon/tests/test_validators.py @@ -273,8 +273,41 @@ class TestValidators(unittest.TestCase): self.assertEqual(rtn, ('jerry', 'oops')) rtn = IS_IN_DB(db, 'person.id', '%(name)s', auto_add=True)('jerry') self.assertEqual(rtn, (3, None)) + # Test it works with reference table + db.define_table('ref_table', + Field('name'), + Field('person_id', 'reference person') + ) + ret = db.ref_table.validate_and_insert(name='test reference table') + self.assertFalse(list(ret.errors)) + ret = db.ref_table.validate_and_insert(name='test reference table', person_id=george_id) + self.assertFalse(list(ret.errors)) + rtn = IS_IN_DB(db, 'ref_table.person_id', '%(name)s')(george_id) + self.assertEqual(rtn, (george_id, None)) + # Test it works with reference table.field and keyed table + db.define_table('ref_person', + Field('name'), + primarykey=['name']) + ret=db.ref_person.insert(name='george') + rtn = IS_IN_DB(db, 'ref_person.name')('george') + self.assertEqual(rtn, ('george', None)) + db.define_table('ref_table_field', + Field('name'), + Field('person_name', 'reference ref_person.name') + ) + ret = db.ref_table_field.validate_and_insert(name='test reference table.field') + self.assertFalse(list(ret.errors)) + ret = db.ref_table_field.validate_and_insert(name='test reference table.field', person_name='george') + self.assertFalse(list(ret.errors)) + vldtr = IS_IN_DB(db, 'ref_table_field.person_name', '%(name)s') + vldtr.options() + rtn = vldtr('george') + self.assertEqual(rtn, ('george', None)) db.person.drop() db.category.drop() + db.ref_person.drop() + db.ref_table.drop() + db.ref_table_field.drop() def test_IS_NOT_IN_DB(self): from gluon.dal import DAL, Field From 6b103f7e3abb0ffb9c37f49688d2982d2cbf7ae2 Mon Sep 17 00:00:00 2001 From: geomapdev Date: Tue, 10 Oct 2017 08:42:17 -0700 Subject: [PATCH 6/6] updated test_validators IS_IN_DB --- gluon/tests/test_validators.py | 37 +++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/gluon/tests/test_validators.py b/gluon/tests/test_validators.py index e6cffc54..d5b93207 100644 --- a/gluon/tests/test_validators.py +++ b/gluon/tests/test_validators.py @@ -285,15 +285,16 @@ class TestValidators(unittest.TestCase): rtn = IS_IN_DB(db, 'ref_table.person_id', '%(name)s')(george_id) self.assertEqual(rtn, (george_id, None)) # Test it works with reference table.field and keyed table - db.define_table('ref_person', + db.define_table('person_keyed', Field('name'), primarykey=['name']) - ret=db.ref_person.insert(name='george') - rtn = IS_IN_DB(db, 'ref_person.name')('george') + db.person_keyed.insert(name='george') + db.person_keyed.insert(name='costanza') + rtn = IS_IN_DB(db, 'person_keyed.name')('george') self.assertEqual(rtn, ('george', None)) db.define_table('ref_table_field', Field('name'), - Field('person_name', 'reference ref_person.name') + Field('person_name', 'reference person_keyed.name') ) ret = db.ref_table_field.validate_and_insert(name='test reference table.field') self.assertFalse(list(ret.errors)) @@ -303,11 +304,37 @@ class TestValidators(unittest.TestCase): vldtr.options() rtn = vldtr('george') self.assertEqual(rtn, ('george', None)) + # Test it works with list:reference table + db.define_table('list_ref_table', + Field('name'), + Field('person_list', 'list:reference person')) + ret = db.list_ref_table.validate_and_insert(name='test list:reference table') + self.assertFalse(list(ret.errors)) + ret = db.list_ref_table.validate_and_insert(name='test list:reference table', person_list=[george_id,costanza_id]) + self.assertFalse(list(ret.errors)) + vldtr = IS_IN_DB(db, 'list_ref_table.person_list') + vldtr.options() + rtn = vldtr([george_id,costanza_id]) + self.assertEqual(rtn, ([george_id,costanza_id], None)) + # Test it works with list:reference table.field and keyed table + #db.define_table('list_ref_table_field', + # Field('name'), + # Field('person_list', 'list:reference person_keyed.name')) + #ret = db.list_ref_table_field.validate_and_insert(name='test list:reference table.field') + #self.assertFalse(list(ret.errors)) + #ret = db.list_ref_table_field.validate_and_insert(name='test list:reference table.field', person_list=['george','costanza']) + #self.assertFalse(list(ret.errors)) + #vldtr = IS_IN_DB(db, 'list_ref_table_field.person_list') + #vldtr.options() + #rtn = vldtr(['george','costanza']) + #self.assertEqual(rtn, (['george','costanza'], None)) db.person.drop() db.category.drop() - db.ref_person.drop() + db.person_keyed.drop() db.ref_table.drop() db.ref_table_field.drop() + db.list_ref_table.drop() + #db.list_ref_table_field.drop() def test_IS_NOT_IN_DB(self): from gluon.dal import DAL, Field