Browse Source

Add soft delete enabled query

Alec Nikolas Reiter 7 years ago
parent
commit
df9baec4c7
2 changed files with 80 additions and 0 deletions
  1. 25 0
      NOTICE
  2. 55 0
      flaskbb/utils/database.py

+ 25 - 0
NOTICE

@@ -0,0 +1,25 @@
+FlaskBB includes code adapted from other Python libaries or resources, including:
+
+sqlalchemy-soft-delete (https://github.com/miguelgrinberg/sqlalchemy-soft-delete) license
+=========================================================================================
+MIT License
+
+Copyright (c) 2016 Miguel Grinberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 55 - 0
flaskbb/utils/database.py

@@ -9,10 +9,13 @@
     :license: BSD, see LICENSE for more details.
     :license: BSD, see LICENSE for more details.
 """
 """
 import pytz
 import pytz
+from flask_sqlalchemy import BaseQuery
+
 from flaskbb.extensions import db
 from flaskbb.extensions import db
 
 
 
 
 def make_comparable(cls):
 def make_comparable(cls):
+
     def __eq__(self, other):
     def __eq__(self, other):
         return isinstance(other, cls) and self.id == other.id
         return isinstance(other, cls) and self.id == other.id
 
 
@@ -29,6 +32,7 @@ def make_comparable(cls):
 
 
 
 
 class CRUDMixin(object):
 class CRUDMixin(object):
+
     def __repr__(self):
     def __repr__(self):
         return "<{}>".format(self.__class__.__name__)
         return "<{}>".format(self.__class__.__name__)
 
 
@@ -70,3 +74,54 @@ class UTCDateTime(db.TypeDecorator):
 
 
         # other dialects are already non-naive
         # other dialects are already non-naive
         return value
         return value
+
+
+class HideableQuery(BaseQuery):
+
+    def __new__(cls, *args, **kwargs):
+        inst = super(HideableQuery, cls).__new__(cls)
+        with_hidden = kwargs.pop('_with_hidden', False)
+        if args or kwargs:
+            super(HideableQuery, inst).__init__(*args, **kwargs)
+            return inst.filter_by(hidden=False) if not with_hidden else inst
+        return inst
+
+    def __init__(self, *args, **kwargs):
+        pass
+
+    def with_hidden(self):
+        return self.__class__(
+            db.class_mapper(self._mapper_zero().class_), session=db.session(), _with_hidden=True
+        )
+
+    def _get(self, *args, **kwargs):
+        return super(HideableQuery, self).get(*args, **kwargs)
+
+    def get(self, *args, **kwargs):
+        include_hidden = kwargs.pop('include_hidden', False)
+        obj = self.with_hidden()._get(*args, **kwargs)
+        return obj if obj is not None and (include_hidden or not obj.hidden) else None
+
+
+class HideableMixin(object):
+    hidden = db.Column(db.Boolean, default=False)
+    hidden_at = db.Column(UTCDateTime(timezone=True), nullable=True)
+    query_class = HideableQuery
+
+    def hide(self, *args, **kwargs):
+        from flaskbb.utils.helpers import time_utcnow
+
+        self.hidden = True
+        self.hidden_at = time_utcnow()
+        db.session.commit()
+        return self
+
+    def unhide(self, *args, **kwargs):
+        self.hidden = False
+        self.hidden_at = None
+        db.session.commit()
+        return self
+
+
+class HideableCRUDMixin(HideableMixin, CRUDMixin):
+    pass