From e4c23366599f979116dfaef843192e8a74d36cec Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 16 Jan 2023 22:50:51 -0600 Subject: [PATCH] Add specific data type options for new table entry form including basic FK / relationship support --- tailbone/templates/tables/create.mako | 163 +++++++++++++++++++++++--- tailbone/views/tables.py | 24 +++- 2 files changed, 166 insertions(+), 21 deletions(-) diff --git a/tailbone/templates/tables/create.mako b/tailbone/templates/tables/create.mako index 6c88bb7a..58bcba18 100644 --- a/tailbone/templates/tables/create.mako +++ b/tailbone/templates/tables/create.mako @@ -118,7 +118,7 @@ v-slot="props" % endif > - {{ props.row.data_type }} + {{ formatDataType(props.row.data_type) }} - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - {{ editingColumnNullable }} - - + + + {{ editingColumnNullable }} + + - - - {{ editingColumnVersioned }} - - + + + {{ editingColumnVersioned }} + + + + + + @@ -638,6 +701,8 @@ ThisPageData.activeStep = null ThisPageData.alembicBranchOptions = ${json.dumps(branch_name_options)|n} + ThisPageData.existingTables = ${json.dumps(existing_tables)|n} + ThisPageData.alembicBranch = ${json.dumps(branch_name)|n} ThisPageData.tableName = '${rattail_app.get_table_prefix()}_widget' ThisPageData.tableModelName = '${rattail_app.get_class_prefix()}Widget' @@ -648,7 +713,10 @@ ThisPageData.tableColumns = [{ name: 'uuid', - data_type: 'String(length=32)', + data_type: { + type: 'String', + length: 32, + }, nullable: false, description: "UUID primary key", versioned: true, @@ -658,17 +726,29 @@ ThisPageData.editingColumn = null ThisPageData.editingColumnName = null ThisPageData.editingColumnDataType = null + ThisPageData.editingColumnDataTypeLength = null + ThisPageData.editingColumnDataTypePrecision = null + ThisPageData.editingColumnDataTypeScale = null + ThisPageData.editingColumnDataTypeReference = null + ThisPageData.editingColumnDataTypeLiteral = null ThisPageData.editingColumnNullable = true ThisPageData.editingColumnDescription = null ThisPageData.editingColumnVersioned = true + ThisPageData.editingColumnRelationship = null ThisPage.methods.tableAddColumn = function() { this.editingColumn = null this.editingColumnName = null this.editingColumnDataType = null + this.editingColumnDataTypeLength = null + this.editingColumnDataTypePrecision = null + this.editingColumnDataTypeScale = null + this.editingColumnDataTypeReference = null + this.editingColumnDataTypeLiteral = null this.editingColumnNullable = true this.editingColumnDescription = null this.editingColumnVersioned = true + this.editingColumnRelationship = null this.editingColumnShowDialog = true this.$nextTick(() => { this.$refs.editingColumnName.focus() @@ -678,16 +758,43 @@ ThisPage.methods.tableEditColumn = function(column) { this.editingColumn = column this.editingColumnName = column.name - this.editingColumnDataType = column.data_type + this.editingColumnDataType = column.data_type.type + this.editingColumnDataTypeLength = column.data_type.length + this.editingColumnDataTypePrecision = column.data_type.precision + this.editingColumnDataTypeScale = column.data_type.scale + this.editingColumnDataTypeReference = column.data_type.reference + this.editingColumnDataTypeLiteral = column.data_type.literal this.editingColumnNullable = column.nullable this.editingColumnDescription = column.description this.editingColumnVersioned = column.versioned + this.editingColumnRelationship = column.relationship this.editingColumnShowDialog = true this.$nextTick(() => { this.$refs.editingColumnName.focus() }) } + ThisPage.methods.formatDataType = function(dataType) { + if (dataType.type == 'String') { + return `sa.String(length=${'$'}{dataType.length})` + } else if (dataType.type == 'Numeric') { + return `sa.Numeric(precision=${'$'}{dataType.precision}, scale=${'$'}{dataType.scale})` + } else if (dataType.type == '_fk_uuid_') { + return 'sa.String(length=32)' + } else if (dataType.type == '_other_') { + return dataType.literal + } else { + return `sa.${'$'}{dataType.type}()` + } + } + + ThisPage.watch.editingColumnDataTypeReference = function(newval, oldval) { + this.editingColumnRelationship = newval + if (newval && !this.editingColumnName) { + this.editingColumnName = `${'$'}{newval}_uuid` + } + } + ThisPage.methods.editingColumnSave = function() { let column if (this.editingColumn) { @@ -698,10 +805,24 @@ } column.name = this.editingColumnName - column.data_type = this.editingColumnDataType + + let dataType = {type: this.editingColumnDataType} + if (dataType.type == 'String') { + dataType.length = this.editingColumnDataTypeLength + } else if (dataType.type == 'Numeric') { + dataType.precision = this.editingColumnDataTypePrecision + dataType.scale = this.editingColumnDataTypeScale + } else if (dataType.type == '_fk_uuid_') { + dataType.reference = this.editingColumnDataTypeReference + } else if (dataType.type == '_other_') { + dataType.literal = this.editingColumnDataTypeLiteral + } + column.data_type = dataType + column.nullable = this.editingColumnNullable column.description = this.editingColumnDescription column.versioned = this.editingColumnVersioned + column.relationship = this.editingColumnRelationship this.editingColumnShowDialog = false } @@ -724,6 +845,10 @@ this.modelImportStatus = "import not yet attempted" this.modelImportProblem = false + for (let column of this.tableColumns) { + column.formatted_data_type = this.formatDataType(column.data_type) + } + let url = '${url('{}.write_model_file'.format(route_prefix))}' let params = { branch_name: this.alembicBranch, diff --git a/tailbone/views/tables.py b/tailbone/views/tables.py index 6f717a58..d11a2923 100644 --- a/tailbone/views/tables.py +++ b/tailbone/views/tables.py @@ -31,6 +31,7 @@ import sys import warnings import six +from sqlalchemy_utils import get_mapper from rattail.util import simple_error @@ -122,8 +123,6 @@ class TableView(MasterView): f.remove('versioned') def get_instance(self): - from sqlalchemy_utils import get_mapper - model = self.model table_name = self.request.matchdict['table_name'] @@ -204,6 +203,9 @@ class TableView(MasterView): branch_name = None kwargs['branch_name'] = branch_name + kwargs['existing_tables'] = [{'name': table.name} + for table in model.Base.metadata.sorted_tables] + kwargs['model_dir'] = (os.path.dirname(model.__file__) + os.sep) @@ -212,6 +214,7 @@ class TableView(MasterView): def write_model_file(self): data = self.request.json_body path = data['module_file'] + model = self.model if os.path.exists(path): if data['overwrite']: @@ -219,6 +222,23 @@ class TableView(MasterView): else: return {'error': "File already exists"} + for column in data['columns']: + if column['data_type']['type'] == '_fk_uuid_' and column['relationship']: + name = column['relationship'] + + table = model.Base.metadata.tables[column['data_type']['reference']] + try: + mapper = get_mapper(table) + except ValueError: + reference_model = table.name.capitalize() + else: + reference_model = mapper.class_.__name__ + + column['relationship'] = { + 'name': name, + 'reference_model': reference_model, + } + self.db_handler.write_table_model(data, path) return {'ok': True}