Add ability to filter recipe lists by tag
authorW. Trevor King <wking@drexel.edu>
Wed, 21 Jul 2010 16:19:50 +0000 (12:19 -0400)
committerW. Trevor King <wking@drexel.edu>
Wed, 21 Jul 2010 16:19:50 +0000 (12:19 -0400)
cookbook/cookbook.py
cookbook/server.py
cookbook/template/recipes.html

index b3e3ed0c045f7b100dc0103002604d7986768029..2c395c5b942d059acc4b5e92fad251824db321d1 100644 (file)
@@ -384,6 +384,14 @@ class Recipe (object):
     Mix ingredients until salamander starts to smoke
     <BLANKLINE>
     Serve warm over rice
+    >>> r.matches_tags(None)
+    True
+    >>> r.matches_tags([])
+    True
+    >>> r.matches_tags(['dinner', 'apprentice'])
+    True
+    >>> r.matches_tags(['dinner', 'dragon'])
+    False
     >>> pprint.pprint(r.to_yaml())
     {'author': 'Merlin',
      'directions': 'Mix ingredients until salamander starts to smoke\\n\\nServe warm over rice',
@@ -439,6 +447,18 @@ class Recipe (object):
             name = name.replace(from_, to)
         return name
 
+    def matches_tags(self, tags):
+        """Return True if this recipe is tagges with each of the tags in tags.
+        """
+        if tags in [None, []]:
+            return True
+        if self.tags == None:
+            return False
+        for t in tags:
+            if t not in self.tags:
+                return False
+        return True
+
     def __str__(self):
         return str(self.__unicode__())
 
@@ -521,6 +541,22 @@ class Cookbook (list):
             self.index[recipe.name] = recipe
             self.index[recipe.clean_name()] = recipe
 
+    def tags(self):
+        """List all tags used in this cookbook.
+        """
+        tags = set()
+        for recipe in self:
+            if recipe.tags != None:
+                tags = tags.union(set(recipe.tags))
+        return sorted(tags)
+
+    def tagged(self, tags=None):
+        """Iterate through all recipes matching the given list of tags.
+        """
+        for recipe in self:
+            if recipe.matches_tags(tags):
+                yield recipe
+
 
 def test():
     import doctest
index 49ddb9ec08e91e048dcf8dfd5fe26160d137e7af..81f820828ceec651a1c0332da0a1fddb272f8001 100644 (file)
@@ -40,14 +40,17 @@ class Server (object):
         pass
 
     @cherrypy.expose
-    def index(self, status='open', assignee='all', target='all'):
+    def index(self, tag=None):
         """Recipe index page.
 
-        Recipes can be filtered or sorted using a variety of criteria.
+        Recipes can be filtered by tag.
         """
+        if isinstance(tag, types.StringTypes):
+            tag = [tag]
         template = self.env.get_template('recipes.html')
         return template.render(cookbook=self.cookbook,
-                               recipes=list(self.cookbook))
+                               recipes=list(self.cookbook.tagged(tag)),
+                               selected_tags=tag)
 
     @cherrypy.expose
     def recipe(self, name=None):
index 02ecddb0edf1b72de5d36107459f5fc23aae3ba2..52e2fedd5a2c8f3a6657737b27b33f38b23dc935 100644 (file)
@@ -1,10 +1,18 @@
 {% extends "base.html" %}
 
 {% block page_title %}
-    Index
+    Index {% if selected_tags %}({{ ', '.join(selected_tags) }}){% endif %}
 {% endblock %}
 
 {% block content %}
+    <form action="">
+      <select name="tag" size="5" multiple="multiple">
+       {% for tag in cookbook.tags() %}
+       <option value="{{ tag }}">{{ tag }}</option>
+       {% endfor %}
+      </select>
+      <input type="submit" value="Show only selected tags" />
+    </form>
     <ul id="recipe-list">
     {% for recipe in recipes %}
         <li><a href="recipe?name={{ recipe.clean_name() }}">