from pylons import url
from floof.lib.base import BaseController, render
-from floof.lib.search import do_search
+from floof.lib.search import parse
log = logging.getLogger(__name__)
return self.save()
c.query = request.params.get('query', '')
- c.artwork = do_search(c.query)
+ c.artwork = parse(c.query).all()
return render('/index.mako')
# TODO: login required
-from floof.model import Art, Tag, TagText
+from floof.model import Art, ArtUser, ArtUserType, Tag, TagText, User
-def do_search(query):
- tags = query.split()
+def parse(search_string):
+ """Parses a search query, and returns a query object on Art.
- tagtexts = TagText.query.filter(TagText.text.in_(tags))
- tagtext_ids = [_.id for _ in tagtexts]
+ Queries can contain:
+ - Regular tags: foo
+ - User relations: by:kalu, of:eevee, for:ootachi
- # Fetch art that has all the tags
- artwork = Art.query.join(Tag) \
- .filter(Tag.tagtext_id.in_(tagtext_ids)) \
- .all()
- return artwork
+ Later:
+ - Negative versions of anything above: -by:eevee, -dongs
+ """
+ # XXX doesn't do negative querying yet.
+ # XXX could use some sane limits.
+ # We'll be building this as we go.
+ q = Art.query
+ terms = search_string.split()
+ for tag in terms:
+ if ':' in tag:
+ # This is a special tag; at the moment, by/for/of to indicate
+ # related users
+ prefix, tag = tag.split(':', 1)
+ # XXX what to do if this fails? abort? return empty query?
+ target_user = User.get_by(name=tag)
-
-# unfinished stuff
-def parse(query):
- words = query.split()
-
- tags = []
- for word in words:
- components = word.split(':')
- if len(components) == 1:
- # tags are plain.
- tags.append(word)
- elif components[0] == "rating":
- if components[1].isnumeric():
- score = int(components[1])
+ if prefix == 'by':
+ rel = ArtUserType.BY
+ elif prefix == 'for':
+ rel = ArtUserType.FOR
+ elif prefix == 'of':
+ rel = ArtUserType.OF
else:
- score = Rating.reverse_options.get(components[1])
+ # Bogus tag. Not sure what to do here, so for the moment,
+ # ignore it
+ continue
- if -1 <= score <= 3:
- pass
- # TODO: Find stuff that has this rating
- # Rating.query.filter(Rating.s)
+ # Inner join to the ArtUser table
+ q = q.join(ArtUser, aliased=True) \
+ .filter(ArtUser.user == target_user) \
+ .filter(ArtUser.type == rel)
- tagtexts = TagText.query.filter(TagText.text.in_(tags))
- tagtext_ids = map(lambda x:x.id, tagtexts)
+ else:
+ # Regular ol' tag
+ q = q.join(Tag, TagText, aliased=True) \
+ .filter(TagText.text == tag)
+ return q