From 6cf96f64954b0b9d8568fa36a6375bbe38bfd70c Mon Sep 17 00:00:00 2001 From: astex <0astex@gmail.com> Date: Thu, 12 May 2016 12:51:59 -0400 Subject: [PATCH 1/5] Add a slug field to the project model. --- app/models/project.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/app/models/project.py b/app/models/project.py index 36e3c77..04e64b9 100644 --- a/app/models/project.py +++ b/app/models/project.py @@ -1,10 +1,37 @@ """Models directly-relating to the top-level project.""" +import re from app.lib.database import db from app.models.base import Model, Tracked, SalesForce class Project(Model, Tracked, SalesForce, db.Model): """A project.""" + client_id = db.Column( + db.Integer, db.ForeignKey('client.id'), nullable=False) + place_id = db.Column( + db.Integer, db.ForeignKey('place.id'), nullable=False) + + name = db.Column(db.Unicode(255), nullable=False) + + @property + def computed_slug(self): + """Compute a slug by doing the following: + - Lowercase the name. + - Replace spaces with "-". Replace "/", "?", "=", "&", and ":" + with nothing. + - Truncate to 200 characters. + - Append a dash and the id. + """ + slug = self.name.lower() + slug = re.sub( + r'(\s|\/|\?|\=|\&|:)/g', + lambda m: '-' if m.group(0).isspace() else '', + slug) + slug = slug[:200] + slug = '{}-{}'.format(slug, self.id) + return slug + slug = db.Column(db.Unicode(255), nullable=False, index=True) + # TODO SQLAlchemy < 1.1 does not support the use of a python enum in Enum # fields, so for now we have to use a list of strings. When 1.1 leaves # beta, this should be ported to the Enum below. @@ -33,12 +60,6 @@ class Project(Model, Tracked, SalesForce, db.Model): 'customer_reviewed', 'approved', 'financed', 'contracted', 'constructed', 'verified', 'paid' ] - - client_id = db.Column( - db.Integer, db.ForeignKey('client.id'), nullable=False) - place_id = db.Column( - db.Integer, db.ForeignKey('place.id'), nullable=False) - name = db.Column(db.Unicode(255), nullable=False) state = db.Column( db.Enum(*states, name='project_states'), default='pending', -- GitLab From 791d83154753c0d736933595f014bd5ec994810e Mon Sep 17 00:00:00 2001 From: astex <0astex@gmail.com> Date: Thu, 12 May 2016 12:54:14 -0400 Subject: [PATCH 2/5] Add a create() method to the rest controller. --- app/controllers/base.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/controllers/base.py b/app/controllers/base.py index 56a963a..6928f39 100644 --- a/app/controllers/base.py +++ b/app/controllers/base.py @@ -73,8 +73,8 @@ class RestController(object): raise NotFound return model - def post(self, data, filter_data): - """Post a new model from a dictionary.""" + def create(self, data, filter_data): + """Creates a model, but does not add it to the database.""" model = self.Model() form = self.get_form(filter_data)(formdata=MultiDict(data)) @@ -82,6 +82,11 @@ class RestController(object): raise BadRequest(form.errors) form.populate_obj(model) + return model + + def post(self, data, filter_data): + """Post a new model from a dictionary.""" + model = self.create(data, filter_data) db.session.add(model) try: commit() -- GitLab From dd8379ddb38623a0570b3823d05475e2040482b2 Mon Sep 17 00:00:00 2001 From: astex <0astex@gmail.com> Date: Thu, 12 May 2016 12:56:17 -0400 Subject: [PATCH 3/5] Add a custom create() method to the project controller which sets the project slug. --- app/controllers/project.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/controllers/project.py b/app/controllers/project.py index e79477c..e4a94a7 100644 --- a/app/controllers/project.py +++ b/app/controllers/project.py @@ -39,6 +39,12 @@ class ProjectController(RestController): state=model.state)) self.commit() + def create(self, data, filter_data): + """Set the project slug after normal creation.""" + model = super(ProjectController, self).create(data, filter_data) + model.slug = model.computed_slug + return model + def post(self, data, filter_data): """Post a new model. -- GitLab From f8658b1acc26fde7c7eb13b6720dad025dff3d71 Mon Sep 17 00:00:00 2001 From: astex <0astex@gmail.com> Date: Thu, 12 May 2016 12:58:43 -0400 Subject: [PATCH 4/5] Do not attempt to set the project slug before the project has an id. --- app/controllers/project.py | 7 +------ app/models/project.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/controllers/project.py b/app/controllers/project.py index e4a94a7..a652525 100644 --- a/app/controllers/project.py +++ b/app/controllers/project.py @@ -39,12 +39,6 @@ class ProjectController(RestController): state=model.state)) self.commit() - def create(self, data, filter_data): - """Set the project slug after normal creation.""" - model = super(ProjectController, self).create(data, filter_data) - model.slug = model.computed_slug - return model - def post(self, data, filter_data): """Post a new model. @@ -115,6 +109,7 @@ class ProjectController(RestController): data.update({'place_id': place.id}) model = super(ProjectController, self).post(data, filter_data) + model.slug = model.computed_slug if filter_data.get('form') == 'salesforce': try: diff --git a/app/models/project.py b/app/models/project.py index 04e64b9..2ed5df1 100644 --- a/app/models/project.py +++ b/app/models/project.py @@ -30,7 +30,7 @@ class Project(Model, Tracked, SalesForce, db.Model): slug = slug[:200] slug = '{}-{}'.format(slug, self.id) return slug - slug = db.Column(db.Unicode(255), nullable=False, index=True) + slug = db.Column(db.Unicode(255), index=True) # TODO SQLAlchemy < 1.1 does not support the use of a python enum in Enum # fields, so for now we have to use a list of strings. When 1.1 leaves -- GitLab From 3d0931371b2236d7eeaa1ef096a716ec7b595952 Mon Sep 17 00:00:00 2001 From: astex <0astex@gmail.com> Date: Mon, 16 May 2016 16:39:14 -0400 Subject: [PATCH 5/5] Use a calculated slug in the project model instead of storing one on the database. --- app/controllers/project.py | 1 - app/models/project.py | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/project.py b/app/controllers/project.py index a652525..e79477c 100644 --- a/app/controllers/project.py +++ b/app/controllers/project.py @@ -109,7 +109,6 @@ class ProjectController(RestController): data.update({'place_id': place.id}) model = super(ProjectController, self).post(data, filter_data) - model.slug = model.computed_slug if filter_data.get('form') == 'salesforce': try: diff --git a/app/models/project.py b/app/models/project.py index 2ed5df1..af250c4 100644 --- a/app/models/project.py +++ b/app/models/project.py @@ -30,7 +30,6 @@ class Project(Model, Tracked, SalesForce, db.Model): slug = slug[:200] slug = '{}-{}'.format(slug, self.id) return slug - slug = db.Column(db.Unicode(255), index=True) # TODO SQLAlchemy < 1.1 does not support the use of a python enum in Enum # fields, so for now we have to use a list of strings. When 1.1 leaves @@ -65,6 +64,12 @@ class Project(Model, Tracked, SalesForce, db.Model): default='pending', nullable=False) + def get_dictionary(self): + """Add the calculated slug to the dictionary.""" + d = super(Project, self).get_dictionary() + d.update({'slug': self.computed_slug}) + return d + class ProjectStateChange(Model, Tracked, db.Model): """A state change of a project.""" -- GitLab