diff options
author | Aaron Williamson <aaron@copiesofcopies.org> | 2012-08-17 00:54:40 -0400 |
---|---|---|
committer | Joar Wandborg <git@wandborg.com> | 2012-09-18 18:10:36 +0200 |
commit | be5be1154fd22c548125ce5a055af1bdfdad9526 (patch) | |
tree | db14a89519b54b0474fca795d8ab242ab8820bfd /mediagoblin/db | |
parent | 09e528acbb4d1321fce5cec8b22fd7fd153bf68a (diff) | |
download | mediagoblin-be5be1154fd22c548125ce5a055af1bdfdad9526.tar.lz mediagoblin-be5be1154fd22c548125ce5a055af1bdfdad9526.tar.xz mediagoblin-be5be1154fd22c548125ce5a055af1bdfdad9526.zip |
Added basic collection functionality
Diffstat (limited to 'mediagoblin/db')
-rw-r--r-- | mediagoblin/db/mixin.py | 53 | ||||
-rw-r--r-- | mediagoblin/db/sql/migrations.py | 14 | ||||
-rw-r--r-- | mediagoblin/db/sql/models.py | 60 | ||||
-rw-r--r-- | mediagoblin/db/sql/util.py | 11 | ||||
-rw-r--r-- | mediagoblin/db/util.py | 2 |
5 files changed, 135 insertions, 5 deletions
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 9f9b8786..929c1c7f 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -143,3 +143,56 @@ class MediaCommentMixin(object): Run through Markdown and the HTML cleaner. """ return cleaned_markdown_conversion(self.content) + + +class CollectionMixin(object): + def generate_slug(self): + # import this here due to a cyclic import issue + # (db.models -> db.mixin -> db.util -> db.models) + from mediagoblin.db.util import check_collection_slug_used + + self.slug = slugify(self.title) + + duplicate = check_collection_slug_used(mg_globals.database, + self.creator, self.slug, self.id) + + if duplicate: + if self.id is not None: + self.slug = u"%s-%s" % (self.id, self.slug) + else: + self.slug = None + + @property + def description_html(self): + """ + Rendered version of the description, run through + Markdown and cleaned with our cleaning tool. + """ + return cleaned_markdown_conversion(self.description) + + @property + def slug_or_id(self): + return (self.slug or self._id) + + def url_for_self(self, urlgen, **extra_args): + """ + Generate an appropriate url for ourselves + + Use a slug if we have one, else use our '_id'. + """ + creator = self.get_creator + + return urlgen( + 'mediagoblin.user_pages.collections_home', + user=creator.username, + collection=self.slug_or_id, + **extra_args) + +class CollectionItemMixin(object): + @property + def note_html(self): + """ + the actual html-rendered version of the note displayed. + Run through Markdown and the HTML cleaner. + """ + return cleaned_markdown_conversion(self.note) diff --git a/mediagoblin/db/sql/migrations.py b/mediagoblin/db/sql/migrations.py index 49798a54..3db51ab9 100644 --- a/mediagoblin/db/sql/migrations.py +++ b/mediagoblin/db/sql/migrations.py @@ -14,7 +14,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/>. -from sqlalchemy import MetaData, Table, Column, Boolean, SmallInteger +from sqlalchemy import MetaData, Table, Column, Boolean, SmallInteger, Integer from mediagoblin.db.sql.util import RegisterMigration @@ -59,3 +59,15 @@ def add_transcoding_progress(db_conn): col = Column('transcoding_progress', SmallInteger) col.create(media_entry) db_conn.commit() + + +@RegisterMigration(4, MIGRATIONS) +def add_mediaentry_collections(db_conn): + metadata = MetaData(bind=db_conn.bind) + + media_entry = Table('core__media_entries', metadata, autoload=True, + autoload_with=db_conn.bind) + + col = Column('collections', Integer) + col.create(media_entry) + db_conn.commit() diff --git a/mediagoblin/db/sql/models.py b/mediagoblin/db/sql/models.py index 7c8c0f99..5862f722 100644 --- a/mediagoblin/db/sql/models.py +++ b/mediagoblin/db/sql/models.py @@ -33,7 +33,7 @@ from sqlalchemy.util import memoized_property from mediagoblin.db.sql.extratypes import PathTupleWithSlashes, JSONEncoded from mediagoblin.db.sql.base import Base, DictReadAttrProxy -from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin +from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin, CollectionMixin, CollectionItemMixin from mediagoblin.db.sql.base import Session # It's actually kind of annoying how sqlalchemy-migrate does this, if @@ -103,6 +103,7 @@ class MediaEntry(Base, MediaEntryMixin): state = Column(Unicode, default=u'unprocessed', nullable=False) # or use sqlalchemy.types.Enum? license = Column(Unicode) + collected = Column(Integer, default=0) fail_error = Column(Unicode) fail_metadata = Column(JSONEncoded) @@ -143,6 +144,11 @@ class MediaEntry(Base, MediaEntryMixin): creator=lambda v: MediaTag(name=v["name"], slug=v["slug"]) ) + collections_helper = relationship("CollectionItem", + cascade="all, delete-orphan" + ) + collections = association_proxy("collections_helper", "in_collection") + ## TODO # media_data # fail_error @@ -348,8 +354,58 @@ class MediaComment(Base, MediaCommentMixin): _id = SimpleFieldAlias("id") +class Collection(Base, CollectionMixin): + __tablename__ = "core__collections" + + id = Column(Integer, primary_key=True) + title = Column(Unicode, nullable=False) + slug = Column(Unicode) + created = Column(DateTime, nullable=False, default=datetime.datetime.now, + index=True) + description = Column(UnicodeText) + creator = Column(Integer, ForeignKey(User.id), nullable=False) + items = Column(Integer, default=0) + + get_creator = relationship(User) + + def get_collection_items(self, ascending=False): + order_col = CollectionItem.position + if not ascending: + order_col = desc(order_col) + return CollectionItem.query.filter_by( + collection=self.id).order_by(order_col) + + _id = SimpleFieldAlias("id") + + +class CollectionItem(Base, CollectionItemMixin): + __tablename__ = "core__collection_items" + + id = Column(Integer, primary_key=True) + media_entry = Column( + Integer, ForeignKey(MediaEntry.id), nullable=False, index=True) + collection = Column(Integer, ForeignKey(Collection.id), nullable=False) + note = Column(UnicodeText, nullable=True) + added = Column(DateTime, nullable=False, default=datetime.datetime.now) + position = Column(Integer) + in_collection = relationship("Collection") + + get_media_entry = relationship(MediaEntry) + + _id = SimpleFieldAlias("id") + + __table_args__ = ( + UniqueConstraint('collection', 'media_entry'), + {}) + + @property + def dict_view(self): + """A dict like view on this object""" + return DictReadAttrProxy(self) + + MODELS = [ - User, MediaEntry, Tag, MediaTag, MediaComment, MediaFile, FileKeynames, + User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames, MediaAttachmentFile] diff --git a/mediagoblin/db/sql/util.py b/mediagoblin/db/sql/util.py index 53260db2..74b5d73e 100644 --- a/mediagoblin/db/sql/util.py +++ b/mediagoblin/db/sql/util.py @@ -17,7 +17,7 @@ import sys from mediagoblin.db.sql.base import Session -from mediagoblin.db.sql.models import MediaEntry, Tag, MediaTag +from mediagoblin.db.sql.models import MediaEntry, Tag, MediaTag, Collection from mediagoblin.tools.common import simple_printer @@ -310,6 +310,15 @@ def clean_orphan_tags(): Session.commit() +def check_collection_slug_used(dummy_db, creator_id, slug, ignore_c_id): + filt = (Collection.creator == creator_id) \ + & (Collection.slug == slug) + if ignore_c_id is not None: + filt = filt & (Collection.id != ignore_c_id) + does_exist = Session.query(Collection.id).filter(filt).first() is not None + return does_exist + + if __name__ == '__main__': from mediagoblin.db.sql.open import setup_connection_and_db_from_config diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py index 540a9244..a8c8c92b 100644 --- a/mediagoblin/db/util.py +++ b/mediagoblin/db/util.py @@ -22,7 +22,7 @@ except ImportError: if use_sql: from mediagoblin.db.sql.fake import ObjectId, InvalidId, DESCENDING from mediagoblin.db.sql.util import atomic_update, check_media_slug_used, \ - media_entries_for_tag_slug + media_entries_for_tag_slug, check_collection_slug_used else: from mediagoblin.db.mongo.util import \ ObjectId, InvalidId, DESCENDING, atomic_update, \ |