On Mon, Jul 27, 2009 at 4:38 AM, Russell
Keith-Magee<freakboy3...@gmail.com> wrote:
> Perhaps I'm missing some of the "neat tricks" that are only possible
> using this approach, but my immediate reaction is that you appear to
> be going to great lengths to avoid the obvious solution - a method
> call. The example you provide with articles(), list(), and item()
> could be just as elegantly expressed using methods that return a list
> of objects or a single object. Method calls can accept multiple
> arguments, and can return multiple values; they can be conditionally
> executed; and they can be combined in infinite variation - not just
> 'chained'.

Hi Russell,

The example given is a simple one.

Consider the following:
    /users/30/articles/25/delete

And then you write:
   1) one view that gets all users for "/users"
   2) one view that gets user with ID 30 for "/30"
   3) one view that gets all articles of user ID 30 for "/articles"
   4) one view that gets article ID 25 for "/25
   5) one view that deletes the selected article for "/delete"

The difference between this approach and simple method calls is that
even the "partial views" are still views that can return HttpResponse
objects. When that happens I made it so that the chain of execution is
short-circuited and no other view is executed.

In my example from http://code.google.com/p/django-catalyst/ in the
view named "item" I select an article and if it doesn't exist I raise
an error. But what if in the example the ID is invalid ... maybe you
want to redirect to the page listing the user's articles (instead of a
general not_found page).

    from django.views.generic.simple import redirect_to

    @Chained(method=articles)
    def item(req, article_id):
        articles = req.context['articles']
        req.context['item'] = articles.get(id=article_id)
        if not req.context['item']:
            return redirect_to('/user/' + req.context['user'].id +
'/articles/list')

In case you use a simple method to do that, you would have to handle
errors with exceptions ...

    try:
        article = get_article(articles_set, article_id)
    except NotFound:
        return redirect_to('/user/' + user.id + '/articles/list')

That's 4 lines off code I want to shave :)
If you also have for those articles views like "edit",
"send_to_friend", "update_state", etc ... if you want to change the
redirection, that's a whole lot of views you need to change.

And another neat thing about chained actions (not supported yet by
what I did, but I intend working on it) is the automatic generation of
URLs. For example you could have something like ...

    @Chained(path_part='/articles')
    def items(req):
        req.context['articles'] = Article.objects;

    @Chained(method=items, path_part='')
    def item(req, article_id):
        articles = req.context['articles']
        req.context['item'] = articles.get(id=article_id)
        if not req.context['item']:
            raise Exception("Provided article_id is invalid!")

    @Chained(method=item)
    def show(req):
        return direct_to_template(req, 'show.html', extra_context=req.context)

And for the "show" view, the URL "/articles/([^/]+)/show" could be
automatically generated ... both in settings.py and in the template
whenever constructing URLs (btw ... I couldn't find a method in the
Django docs for this ... in templates are the URLs hardcoded?).

And I know this seems like a lot of "magic", making implicit
assumptions and wiring, but when you look at a URL like ...
    /users/30/articles/25/delete
    /users/30/articles/25/comments/20/mark_spam

... if it uses chained views, then you'll immediately know where to
look when you want to modify something. It makes refactoring easy
(including refactoring of Urls) because it has a simple to remember
structure/flow. That wouldn't be the case for simple methods.

And I know this doesn't count, but in Emacs I'm also using yasnippets
(a plugin that provides Textmate-like snippets) ... and I have a
"crud" snippet that generates all the required actions (views). It's
really neat writing a crud interface (with clear code) in minutes :)


--
Alexandru, Nedelcu
http://alexn.org

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to