aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/db/base.py
diff options
context:
space:
mode:
authorJessica Tallon <tsyesika@tsyesika.se>2015-10-01 13:23:33 +0200
committerJessica Tallon <tsyesika@tsyesika.se>2015-10-07 14:40:44 +0200
commit30852fda1c119e6031914b983920898cd57d5aa9 (patch)
treee7727c3425d97ecae95f7b738023475f8ecbe11a /mediagoblin/db/base.py
parent0f3bf8d4b180ffd1907d1578e087522aad7d9158 (diff)
downloadmediagoblin-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.py54
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