Re: Blueprint usage advice
- From:
- Steven Kryskalla
- Date:
- 2012-10-22 @ 05:04
On Sun, Oct 21, 2012 at 6:02 PM, Desmond Rivet <desmond.rivet@gmail.com> wrote:
> It's a blogging system (I know, I know...there are a lot of these.
> It's a learning project :-). The blog entries map to flat files on
> disk, and they can be nested arbitrarily into folders. The folders
> leading up the blog entry becomes the "category".
>
> An example of an "action" would be "tags". So you can have a URL like this:
>
> /cooking/indian/tags/recipes
>
> And that returns all the entries in the "cooking/indian" category that
> have a tag of "recipes". You can start the tag search from any point
> in the category tree. So these work too:
>
> /cooking/tags/recipes
> /tags/recipes
>
> Another example is the "search" action, which does a full text search
> through the entries, starting from the category given.
Ah ok, I thought maybe it was going to refer to different types of
objects, like /users/search and /posts/search.
In that case, you might also consider just using query string params:
/?tags=recipes
/?search=recipes
/cooking?tags=recipes
/cooking?search=recipes
/cooking/indian?tags=recipes
/cooking/indian?search=recipes
That way you can also do ?tags=recipes&search=indian to do a search
and limit to a specific tag.
> So, with respect to my original posting, I guess I'm asking whether
> one should use one blueprint with a url_prefix to capture the
> category, or whether one should use several blueprints to modularize
> the actions (tag, search, etc.).
I think it'd be more natural to organize the functionality into a
CategoryBlueprint which has three view methods:
* index (shows a list of posts in that category)
* tag (same thing as index but restricts posts to a certain tag)
* search (same thing as index but searches the title/body of posts)
The only way I would organize the blueprints the other way around
(IndexBlueprint, TagBlueprint, SearchBlueprint) was if those
blueprints could be applied to multiple objects/resources/models (e.g.
users, posts, comments). And at that point, you might also switch to
class based views instead of blueprints.
> I don't really thing the logic would be any different based on the
> category (although I guess it could be, in theory). Right now, the
> category is just a "root" for the action.
Yea this was just my thinking about it applying to different types of
objects, thus the need for different logic. It's not needed in your
example.
> I decided to implement the tagging and search as optional "plugins"
> which you can choose not to configure. If the notion of a "plugin"
> maps to the notion of a "blueprint", then I find it a bit easier to
> think about.
> ...
> I kind of want both. I'd like to package things like "tagging" and
> "search" into separate modules. But they both work off of a "category
> context", so I'd like to factor that out as well.
Flask doesn't really prescribe any solutions to get that level of
modularity. You have to rely on python's OO features, which is why I
said to forget about flask & blueprints when coming up with the
design. You could do something like this (remember, not necessarily
any flask involved):
class ListView(object)
this provides a method like "get_items", which must be overridden
class CategoryView(ListView)
this implements "get_items" to return the list of posts in a category
class Modifier(object):
def __init__(self, listview):
self.listview = listview
class TagModifier(object)
def tagged(self, tagname): ...
the "tagged" method calls self.listview.get_items, then filters out
any posts with tags that don't match
class SearchModifier(object)
def search(self, query): ...
the "search" method calls self.listview.get_items, then filters out
any posts whose title/body don't match the search term
class CustomCategoryView(CategoryView):
def __init__(self):
super(CustomCategoryView).__init__()
self.tagmod = TagModifier(self)
self.searchmod = SearchModifier(self)
now this view has the default category listing behavior, plus it can
use the self.tagmod.tagged and self.searchmod.searchview methods
This is using "composition over inheritance":
http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
If you want to use inheritance instead of composition, you could do
CustomCategoryView(TagModifier, SearchModifier, CategoryView),
changing TagModifier and SearchModifier to use super(...,
self).get_items() instead of self.listview.get_items().
With this approach in place, you can then add flask's pluggable
(class-based) views, or use blueprint factories. I have an example of
a blueprint factory kind of thing here:
https://bitbucket.org/lost_theory/flask-stripe-blueprint/src/513aae2dc2be/itemshop/__init__.py?at=default#cl-15
Either way, first you design your objects, then you wire them up to
flask, because flask is very flexible! (just like python)
-steve
Re: Blueprint usage advice
- From:
- Steven Kryskalla
- Date:
- 2012-10-22 @ 05:12
On Sun, Oct 21, 2012 at 10:04 PM, Steven Kryskalla <skryskalla@gmail.com> wrote:
> class Modifier(object):
> def __init__(self, listview):
> self.listview = listview
>
> class TagModifier(object)
> def tagged(self, tagname): ...
> the "tagged" method calls self.listview.get_items, then filters out
> any posts with tags that don't match
>
> class SearchModifier(object)
> def search(self, query): ...
> the "search" method calls self.listview.get_items, then filters out
> any posts whose title/body don't match the search term
Sorry, last minute edit broke my pseudocode :) These should read:
class Modifier(object):
def __init__(self, listview):
self.listview = listview
class TagModifier(Modifier):
def tagged(self, tagname): ...
class SearchModifier(Modifier):
def search(self, query): ...
And here is some real code demonstrating composition vs. inheritance:
https://gist.github.com/3929765
-steve