fixed search query (awesome now thanks vee =]), tag links, default routing is back...
authorNick Retallack <nickretallack@gmil.com>
Mon, 5 Oct 2009 17:37:50 +0000 (10:37 -0700)
committerNick Retallack <nickretallack@gmil.com>
Mon, 5 Oct 2009 17:37:50 +0000 (10:37 -0700)
1  2 
floof/config/routing.py
floof/controllers/art.py
floof/controllers/search.py
floof/model/art.py
floof/public/layout.css
floof/templates/art/show.mako

diff --combined floof/config/routing.py
@@@ -25,13 -25,8 +25,18 @@@ def make_map()
      map.connect('/account/login', controller='account', action='login')
      map.connect('/account/login_begin', controller='account', action='login_begin', **require_POST)
      map.connect('/account/login_finish', controller='account', action='login_finish')
 +    map.connect('/account/logout', controller='account', action='logout', **require_POST)
 +    map.connect('/account/register', controller='account', action='register')
 +    map.connect('/account/register_finish', controller='account', action='register_finish', **require_POST)
  
 +    map.connect('/users', controller='users', action='list')
 +    map.connect('/users/{name}', controller='users', action='view')
 +
 +    map.connect('/search', controller='search', action='index')
 +
++    # default routing is back so we can test stuff.
++    # please don't take it away until we have some more core features in.
+     map.connect('/{controller}/{action}')
+     map.connect('/{controller}/{action}/{id}')
      return map
diff --combined floof/controllers/art.py
@@@ -19,8 -19,8 +19,8 @@@ class ArtController(BaseController)
      def new(self):
          """ New Art! """
          return render("/art/new.mako")
 -        
 -        
 +
 +
      def upload(self):
          print "PARAMS", request.params
          Art(uploaded_by=c.user, **request.params)
  
      def show(self, id):
          c.art = Art.get(id)
+         c.your_score = c.art.user_score(c.user)
          return render("/art/show.mako")
+         
+     # should force logged in on these things
      def tag(self, id):
          art = Art.get(id)
          art.add_tags(request.params["tags"], c.user)
          elixir.session.commit()
-         redirect_to(action="show", id=art.id)
+         redirect_to(action="show", id=art.id)
+     
+     def rate(self, id):
+         art = Art.get(id)
+         art.rate(request.params["score"], c.user)
+         elixir.session.commit()
+         redirect_to(action="show", id=art.id)
@@@ -13,16 -13,43 +13,16 @@@ import elixi
  class SearchController(BaseController):
  
      def index(self):
 -        # Return a rendered template
 -        #return render('/search.mako')
 -        # or, return a response
 -        return 'Hello World'
 -
 -    def results(self):
 -        """ Search, implemented the stupid way! """
 -        query = request.params.get('query','')
 -        words = query.split()
 +        """Search, implemented the stupid way!"""
 +        query = request.params.get('query', '')
 +        tags = 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])
 -                else:
 -                    score = Rating.reverse_options.get(components[1])
 -                
 -                if -1 <= score <= 3:
 -                    pass
 -                    # TODO: Find stuff that has this rating
 -                    # Rating.query.filter(Rating.s)
 -                
 -                
 -        
 -
          tagtexts = TagText.query.filter(TagText.text.in_(tags))
 -        tagtext_ids = map(lambda x:x.id, tagtexts)
 +        tagtext_ids = [_.id for _ in tagtexts]
 +
 +        # Fetch art that has all the tags
 +        c.artwork = Art.query.join(Tag) \
-                        .filter(Tag.id.in_(tagtext_ids)) \
++                       .filter(Tag.tagtext_id.in_(tagtext_ids)) \
 +                       .all()
  
-         return render('/index.mako')
 -        # TODO: this is wrong.  Please fix it so it returns art that has all the tags.
 -        art_tag_pairs = elixir.session.query(Art,Tag).filter(Art.id == Tag.art_id).\
 -            filter(Tag.tagtext_id.in_(tagtext_ids)).all()
 -        
 -        # just the art please.
 -        c.artwork = map(lambda x: x[0], art_tag_pairs)
+         return render('/index.mako')
diff --combined floof/model/art.py
@@@ -11,15 -11,15 +11,14 @@@ import elixi
  from pylons import config
  
  from floof.lib.file_storage import get_path, save_file
- from floof.lib.dbhelpers import find_or_create
+ from floof.lib.dbhelpers import find_or_create, update_or_create
  
 -
  class Art(Entity):
      title = Field(Unicode(120))
      original_filename = Field(Unicode(120))
      hash = Field(String)
  
 -    uploaded_by = ManyToOne('User')    
 +    uploaded_by = ManyToOne('User')
      tags = OneToMany('Tag')
  
      # def __init__(self, **kwargs):
@@@ -34,7 -34,7 +33,7 @@@
  
      def set_file(self, file):
          self.hash = save_file("art", file)
 -        
 +
      file = property(get_path, set_file)
  
      def get_path(self):
                      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)
  
  
+     def rate(self, score, user):
+         return update_or_create(Rating, {"rater":user, "art":self}, {"score":score})
+         
+     def user_score(self, user):
+         rating = Rating.get_by(rater=user, art=self)
+         if rating:
+             return rating.score
+         return Rating.default
      def __unicode__(self):
          return self.get_path()
  
@@@ -71,7 -82,7 +79,7 @@@
  class Tag(Entity):
      # look into how ondelete works.  This just sets a database property.
      art = ManyToOne('Art', ondelete='cascade')
-     tagger = ManyToOne('User')
+     tagger = ManyToOne('User', ondelete='cascade')
      tagtext = ManyToOne('TagText')
  
      # this text setter is no longer useful since I changed the way Art#add_tags works
          if not self.tagtext:
              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
+         return self.text
+         
+ class Rating(Entity):
+     art = ManyToOne('Art', ondelete='cascade')
+     rater = ManyToOne('User', ondelete='cascade')
+     score = Field(Integer)
+         
+     options = {-1:"sucks", 0:"undecided", 1:"good", 2:"great"}
+     default = 0
+     # options = ["sucks","neutral","good","great"]
+     
+ Rating.reverse_options = dict (zip(Rating.options.values(), Rating.options.keys()))
diff --combined floof/public/layout.css
@@@ -1,6 -1,3 +1,6 @@@
 +/*** Main layout ***/
 +body { font-family: sans-serif; font-size: 12px; }
 +
  #header { padding: 1em; background: #c0c0c0; }
  #header #user { text-align: right; }
  
@@@ -9,15 -6,4 +9,14 @@@
  #footer { padding: 1em; background: #c0c0c0; }
  
  .full {display:block;}
 -.selected {color:red;}
 +
 +/*** Common bits and pieces ***/
 +/* General form layout */
 +dl.form { margin: 1em 0; padding-left: 1em; border-left: 0.5em solid gray; }
 +dl.form dt { padding-bottom: 0.25em; font-style: italic; }
 +dl.form dd { margin-bottom: 0.5em; }
 +
 +
 +
 +/*** Individual page layout ***/
++.selected {color:red;}
@@@ -1,5 -1,7 +1,7 @@@
  <%inherit file="/base.mako" />
  
+ <%! from floof.model.art import Rating %>
  <h1>View Art</h1>
  
  ${h.form (h.url_for (controller='art', action='tag', id=c.art.id), multipart=True)}
@@@ -9,9 -11,17 +11,17 @@@ ${h.end_form()
  
  % for tag in c.art.tags:
  <a href="${h.url_for (controller='tag', action='delete', id=tag.id)}">x</a> 
--<a href="${h.url_for (controller='search', action='results')}?query=${tag}">${tag}</a>
++<a href="${h.url_for (controller='search', action='index')}?query=${tag}">${tag}</a>
  % endfor
  
+ What do you think?
+ % for score,text in sorted(Rating.options.items()):
+ <a href="${h.url_for(controller='art', action='rate', id=c.art.id)}?score=${score}" \
+ % if c.your_score == score:
+ class="selected" \
+ % endif
+ >${text}</a> 
+ % endfor
  
  <img class="full" src="${c.art.get_path()}">