Malcolm, thank you for the elaborate response, much appreciated!
On Jan 21, 10:51 am, Malcolm Tredinnick <[email protected]> wrote: > On Wed, 2009-01-21 at 01:32 -0800, Guyon Morée wrote: > > Hi, > > > I've built a bunch of 'normal' views rendering templates and > > processing POST's. > > > Now, I'd like to build a API for my site, based on JSON. When building > > this API I noticed most of the views are 99% the same, > > Excellent. :-) > > That's the ideal situation. > > > except for > > outputting JSON instead of HTML templates. > > > Any ideas how I could reduce duplication of code in these cases? > > A rough "general" pattern here is that most of your view is constructing > a dictionary of values -- and it could be some other data structure, but > we'll assume a dictionary here -- that will be used to generate the > output. For templates, this dictionary is usually just passed to a > Context class to create the template context. But there might be some > other transformation you have to do to it first. > > In any case, that's where the split happens. One function is responsible > for collecting the output data and putting it into a neutral data > structure -- again, let's say, a dictionary. That output data will be > the same, no matter what the format of the response. > > Then you decide, based on the request, whether to process that data into > a json response, or an Atom response, or an HTML templated response. > Each of those "convert the dictionary into an output response" could be > another function. Those functions might have to do some further munging > of the dictionary for their own circumstances -- for example, the > template version might drop in some extra variables for "the current > page" or something related to tab ids -- but, by and large, they'll all > be handing off the data to a different renderer. Either > simplejson.dumps, or render_to_string (or render_to_response) or > whatever. > > In pseudo-code: > > def my_view(request, ....): > result_data = gather_the_data(...) > > if response_type == "html": > return render_to_html(request, result_data) > if response_type == "json": > return HttpResponse(render_to_json(request, > result_data)) > > def render_to_html(request, result_data): > template_name = > get_template_name(result_data["target_name"]) > return render_to_response(template_name, result_data) > > def render_to_json(request, result_data): > return simplejson.dumps(result_data) > > This is very simplistic, but it hopefully gets the idea across. > "result_data" is the neutral form, gather_the_data() does all the heavy > lifting and the various presentation functions do the final bit. > > Depending on how your code works out, it's probably going to be easy to > make this all more regular, too. A function to work out the response > type, which is then used as a key to look up a dictionary of > presentation functions to call (render_to_html, render_to_json, etc). > > Daniel Lindsley has a blog post about a version of this that uses > templates for all the output formats -- see [1]. I tend to go for the > "presentation functions" approach, since templates don't feel like the > right solution for json or Atom. But the principle is the same and > Daniel's post (and a follow-up one James Bennett did at [2]) should give > you some more ideas. > > [1]http://toastdriven.com/fresh/multiresponse/ > [2]http://www.b-list.org/weblog/2008/nov/29/multiresponse/ > > Regards, > Malcolm --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---

