diff options
author | Jessica Tallon <tsyesika@tsyesika.se> | 2015-10-01 13:23:33 +0200 |
---|---|---|
committer | Jessica Tallon <tsyesika@tsyesika.se> | 2015-10-07 14:40:44 +0200 |
commit | 30852fda1c119e6031914b983920898cd57d5aa9 (patch) | |
tree | e7727c3425d97ecae95f7b738023475f8ecbe11a /mediagoblin/db/base.py | |
parent | 0f3bf8d4b180ffd1907d1578e087522aad7d9158 (diff) | |
download | mediagoblin-30852fda1c119e6031914b983920898cd57d5aa9.tar.lz mediagoblin-30852fda1c119e6031914b983920898cd57d5aa9.tar.xz mediagoblin-30852fda1c119e6031914b983920898cd57d5aa9.zip |
Add the __model_args__ deletion code
This adds the "deleted" fields to the models as well as a new
__model_args__ section whcih supports the option for changing the
deletion type. Deletion is now handled by choosing a deletion method
based on the __model_args__["deletion"] setting, for example if it's
soft deletion it will call Model.soft_delete()
Diffstat (limited to 'mediagoblin/db/base.py')
-rw-r--r-- | mediagoblin/db/base.py | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/mediagoblin/db/base.py b/mediagoblin/db/base.py index 6acb0b79..a425343b 100644 --- a/mediagoblin/db/base.py +++ b/mediagoblin/db/base.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - +import datetime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import inspect @@ -26,6 +26,16 @@ if not DISABLE_GLOBALS: class GMGTableBase(object): + # Deletion types + HARD_DELETE = "hard-deletion" + SOFT_DELETE = "soft-deletion" + + __default_model_args__ = { + "deletion": HARD_DELETE, + "soft_deletion_field": "deleted", + "soft_deletion_retain": ("id",) + } + @property def _session(self): return inspect(self).session @@ -37,6 +47,11 @@ class GMGTableBase(object): if not DISABLE_GLOBALS: query = Session.query_property() + def get_model_arg(self, argument): + model_args = self.__default_model_args__.copy() + model_args.update(getattr(self, "__model_args__", {})) + return model_args.get(argument) + def get(self, key): return getattr(self, key) @@ -56,6 +71,43 @@ class GMGTableBase(object): sess.flush() def delete(self, commit=True): + """ Delete the object either using soft or hard deletion """ + if self.get_model_arg("deletion") == self.HARD_DELETE: + return self.hard_delete(commit) + elif self.get_model_arg("deletion") == self.SOFT_DELETE: + return self.soft_delete(commit) + else: + raise ValueError( + "__model_args__['deletion'] is an invalid value %s" % ( + self.get_model_arg("deletion") + )) + + def soft_delete(self, commit): + # Find the deletion field + field_name = self.get_model_arg("soft_deletion_field") + + # We can't use self.__table__.columns as it only shows it of the + # current model and no parent if polymorphism is being used. This + # will cause problems for example for the User model. + if field_name not in dir(type(self)): + raise ValueError("Cannot find soft_deletion_field") + + # Store a value in the deletion field + setattr(self, field_name, datetime.datetime.utcnow()) + + # Iterate through the fields and remove data + retain_fields = self.get_model_arg("soft_deletion_retain") + for field_name in self.__table__.columns.keys(): + # should we skip this field? + if field_name in retain_fields: + continue + + setattr(self, field_name, None) + + # Save the changes + self.save(commit) + + def hard_delete(self, commit): """Delete the object and commit the change immediately by default""" sess = self._session assert sess is not None, "Not going to delete detached %r" % self |