From: Eevee Date: Sat, 5 Dec 2009 22:24:43 +0000 (-0800) Subject: Added for:/of: tagging capability. X-Git-Url: http://git.veekun.com/zzz-floof.git/commitdiff_plain/73fe4db9e53797b3dff9d5a369cb838daebeaee4 Added for:/of: tagging capability. TagMixin is no more. --- diff --git a/floof/controllers/tag.py b/floof/controllers/tag.py index e5ce85b..e57d0c5 100644 --- a/floof/controllers/tag.py +++ b/floof/controllers/tag.py @@ -1,16 +1,18 @@ import logging +import re -from pylons import request, response, session, tmpl_context as c, h +from pylons import request, response, session, tmpl_context as c, url from pylons.controllers.util import abort, redirect +import elixir +from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User from floof.lib.base import BaseController, render -from pylons import url +from floof.lib.dbhelpers import find_or_create +from floof.lib import helpers as h +from sqlalchemy import func log = logging.getLogger(__name__) -import elixir -from floof.model import Art, Tag - class TagController(BaseController): # TODO: login required @@ -23,7 +25,77 @@ class TagController(BaseController): # TODO: login required def create(self, art_id): c.art = h.get_object_or_404(Art, id=art_id) - c.art.add_tags(request.params.get("tags",""), c.user) + + tag_string = request.params.get('tags', '') + + # Add or remove tags + bad_tags = [] + for tag_text in tag_string.split(): + original_tag_text = tag_text + tag_text = tag_text.lower() + + # Adding or removing a tag? + if tag_text[0] == '-': + add = False + tag_text = tag_text[1:] + else: + # Allow "+foo" to mean "add foo" + if tag_text[0] == '+': + tag_text = tag_text[1:] + add = True + + # Check for special namespaces + prefix = None + if ':' in tag_text: + prefix, tag_text = tag_text.split(':', 1) + if prefix not in ['by', 'for', 'of']: + # This is bogus. Skip it. + bad_tags.append(original_tag_text) + continue + + if prefix == 'by': + # XXX this needs supporting. silently ignore for now + continue + + # Must be 3-50 alphanumeric characters + if not re.match('^[a-z0-9]{3,50}$', tag_text): + bad_tags.append(original_tag_text) + continue + + # Do work! + if prefix: + target_user = User.query.filter(func.lower(User.name) == tag_text) \ + .one() + + # Special tag; at the moment, just a relationship + if prefix == 'by': + rel = ArtUserType.BY + elif prefix == 'for': + rel = ArtUserType.FOR + elif prefix == 'of': + rel = ArtUserType.OF + + user_assoc_data = dict(art=c.art, user=target_user, type=rel) + if add: + find_or_create(ArtUser, **user_assoc_data) + + else: + # XXX this will die for nonassociations + user_assoc = ArtUser.get_by(art=c.art, **user_assoc_data) + user_assoc.delete() + + else: + # Regular tag + if add: + tag = find_or_create(TagText, text=tag_text) + find_or_create(Tag, art=c.art, tagger=c.user, tagtext=tag) + + else: + tag = TagText.get_by(text=tag_text) + if tag: + # XXX this will die + tag_assoc = Tag.get_by(art=c.art, tagger=c.user, tagtext=tag) + tag_assoc.delete() + elixir.session.commit() redirect(url('show_art', id=c.art.id)) - diff --git a/floof/model/art.py b/floof/model/art.py index ea6d6ee..0452e32 100644 --- a/floof/model/art.py +++ b/floof/model/art.py @@ -44,7 +44,6 @@ class Art(Entity): def participants(self): return (au.user for au in self.art_users if au.type == ArtUserType.OF) - class ArtUserType(object): BY = 1 FOR = 2 diff --git a/floof/model/tags.py b/floof/model/tags.py index 1a41278..b0a7072 100644 --- a/floof/model/tags.py +++ b/floof/model/tags.py @@ -1,7 +1,5 @@ from elixir import * from art import Art -from floof.lib.dbhelpers import find_or_create, update_or_create - class Tag(Entity): # look into how ondelete works. This just sets a database property. @@ -14,33 +12,9 @@ class Tag(Entity): return "(broken)" return unicode(self.tagtext) - class TagText(Entity): text = Field(Unicode(50)) # gotta enforce this somehow tags = OneToMany('Tag') def __unicode__(self): return self.text - - -class TagMixin(object): - def add_tags(self, tags, user): - for text in tags.split(): - if text[0] == '-': - # Nega-tags - tagtext = TagText.get_by(text=text[1:]) - if tagtext: - tag = Tag.get_by(art=self, tagger=user, tagtext=tagtext) - if tag: - elixir.session.delete(tag) - - else: - if len(text) > 50: - raise "Long Tag!" # can we handle this more gracefully? - # sqlite seems happy to store strings much longer than the supplied limit... - - # elixir should really have its own find_or_create. - tagtext = find_or_create(TagText, text=text) - tag = find_or_create(Tag, art=self, tagger=user, tagtext=tagtext) - -Art.__bases__ += (TagMixin, )