I'm of two minds on this.  It's a one-liner to implement as I've done it,
but my implementation hides the rich argument set available in
simplejson.dumps():

dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None, encoding='utf-8',
default=None, use_decimal=False, **kw)

It also hides the arguments available to XML().

If implemented,  I think it would be good to provide as many of the
arguments as make sense for its use as a helper -- which probably means all
of them.

Regarding controller vs view, I think it should be available, like all the
other helpers, in either context.

Whether we implement it or not,  I think the technique of passing python
objects into javascript at render time with json serialization is quite
useful and merits an example in the next revision of the book.

Cheers,
Mike


On Sat, Jul 24, 2010 at 9:18 PM, Scott <blueseas...@gmail.com> wrote:

> I think the JSON helper function should be implemented.  This logic
> should be contained within the controller and not within the view as I
> would deem it business logic and not rendering logic.
>
> On Jul 24, 7:52 pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> > Should we have a JSON helper (same as you JD)?
> >
> > On Jul 24, 1:15 pm, Michael Ellis <michael.f.el...@gmail.com> wrote:
> >
> > > Something good has come out of this: while looking for a workaround I
> > > learned about simplejson.dumps().  So now I've defined my own little
> helper
> > > JD()
> >
> > > import simplejson
> > > def JD(obj):
> > >     return XML(simplejson.dumps(obj,indent=4))
> >
> > > In my view (or controller) I can lump into one variable everything I'm
> going
> > > to need to pass into my js at render time, e.g.
> >
> > > PT = dict(
> > >     updatenow=False,
> > >     schartoptions = dict(
> > >         type ='bar',
> > >         barColor ='green',
> > >         chartRangeMin = chartmin,
> > >         chartRangeMax = chartmax,
> > >         )
> > >     ## add more objects here ...
> > >     )
> >
> > > then put a single line at the top of my js script and reference
> everything
> > > as part of that namespace, e.g.
> > > <script type="text/javascript">
> > >     ...
> > >     var PT = {{=JD(PT)}};
> > >     ...
> >
> > >     $(#something).sparkline( ..., PT.schartoptions);
> > >     ...
> > > </script>
> >
> > > The JD(PT) expands to a nicely indented js declaration, e.g.
> >
> > > var PT = {
> > >     "updatenow": false,
> > >     "schartoptions": {
> > >         "chartRangeMin": 0,
> > >         "barColor": "green",
> > >         "type": "bar",
> > >         "chartRangeMax": 1
> > >     }
> >
> > > };
> >
> > > What's also cool is that if all or part of that declaration corresponds
> to
> > > data coming in from a getJSON() loop  after the page is loaded, then
> > > everything's already defined and initialized.
> >
> > > This feels like a definite improvement over what I was doing before.
> Far
> > > less clutter and definitely DRY'er.
> >
> > > Cheers,
> > > Mike
> >
> > > On Sat, Jul 24, 2010 at 9:34 AM, Phyo Arkar <phyo.arkarl...@gmail.com
> >wrote:
> >
> > > > I am also doing more and more in JS for views. Even search engine for
> > > > tables, i am using JQGrid's local search (at latest version if
> JQGrid).It
> > > > dont need server side at all for search to work, which make it a lot
> faster
> > > > + lesser hit on server performance.
> >
> > > > On Sat, Jul 24, 2010 at 7:53 PM, Michael Ellis <
> michael.f.el...@gmail.com>wrote:
> >
> > > >> My bad.  It does work.  In my earlier attempt to use it I forgot
> that a
> > > >> for loop variable isn't an object reference when looping over a list
> of
> > > >> strings.  So the value of schartoptions wasn't being altered at all,
> just
> > > >> the loop variable.
> >
> > > >> I'm still in favor of an alternate operator, though.  As it is now,
> I've
> > > >> moved all my chart options inside the script tag e.g.
> >
> > > >>     var schartoptions = {
> > > >>         type: 'bar',
> > > >>         barColor: 'green',
> > > >>         chartRangeMin: '{{=chartmin}}',
> > > >>         chartRangeMax: '{{=chartmax}}'
> > > >>     };
> >
> > > >> and substitute only the things that have to be determined  at run
> time
> > > >> rather than clutter up my expressions by wrapping them in XML().
> >
> > > >> I'd much rather code in python than js, but I'm beginning to feel
> that
> > > >> using more js and less python in views makes a lot of sense.
> >
> > > >> Thanks,
> > > >> Mike
> >
> > > >> On Sat, Jul 24, 2010 at 8:40 AM, mdipierro <mdipie...@cs.depaul.edu
> >wrote:
> >
> > > >>> I am confused:
> > > >>> Does this now work?
> >
> > > >>> {{
> > > >>> schartoptions = """{
> > > >>>    type: 'bar',
> > > >>>    barColor: 'green',
> > > >>>    chartRangeMin: '%d',
> > > >>>    chartRangeMax: '%d'
> > > >>>    }
> > > >>>    """%(chartmin,chartmax)
> >
> > > >>> }}
> >
> > > >>> and later on I use the variables within a script tag, e.g.
> >
> > > >>> <script type="text/javascript">
> > > >>>    /* <![CDATA[ */
> > > >>>    $("#{{=ks+kc}}").sparkline(data.wsc.{{=ks}}.{{=kc}},
> > > >>> {{=XML(schartoptions)}}
> > > >>> </script>
> >
> > > >>> If not, what are chartmin and chartmax, are they themselves
> helpers?
> >
> > > >>> On Jul 24, 7:28 am, Michael Ellis <michael.f.el...@gmail.com>
> wrote:
> > > >>> > Massimo, I'm not following you.  I tried using XML (see earlier
> post)
> > > >>> and it
> > > >>> > had no effect.  Does it only work if applied immediately before
> the =
> > > >>> > operator?
> >
> > > >>> > Also, I think ":=" or something similar is much cleaner than
> wrapping
> > > >>> > everything in a function call.
> >
> > > >>> > Cheers,
> > > >>> > Mike
> >
> > > >>> > On Sat, Jul 24, 2010 at 8:19 AM, mdipierro <
> mdipie...@cs.depaul.edu>
> > > >>> wrote:
> > > >>> > > This
> >
> > > >>> > > {{:=never_escaped}}
> >
> > > >>> > > would be the same as
> >
> > > >>> > > {{=XML(ever_escaped)}}
> >
> > > >>> > > so why introduce new syntax?
> >
> > > >>> > > On Jul 24, 7:14 am, Michael Ellis <michael.f.el...@gmail.com>
> wrote:
> > > >>> > > > I could happily live with a solution that adds a 'no escape'
> > > >>> operator to
> > > >>> > > the
> > > >>> > > > template language, e.g.
> >
> > > >>> > > > {{:=never_escaped}}
> >
> > > >>> > > > vs
> >
> > > >>> > > > {{=always_escaped}}
> >
> > > >>> > > > 1. Backward compatible,
> >
> > > >>> > > > 2. Safe by default,
> >
> > > >>> > > > 3. Allows designer to decide what's safe and what isn't,
> >
> > > >>> > > > 4. Seems like  an easier fix than trying to make the
> rendering code
> > > >>> smart
> > > >>> > > > enough to always distinguish js from html strings.
> >
> > > >>> > > > Just a thought,
> > > >>> > > > Mike
> >
> > > >>> > > > On Sat, Jul 24, 2010 at 4:02 AM, mdipierro <
> > > >>> mdipie...@cs.depaul.edu>
> > > >>> > > wrote:
> > > >>> > > > > Thadeus,
> >
> > > >>> > > > > This was a security fix. We had a a security review and
> this was
> > > >>> > > > > determined to be a weakness. The code by Mike Ellis broke
> not
> > > >>> because
> > > >>> > > > > of the fix but because it incorrectly implicitly assumed
> that
> > > >>>  the
> > > >>> > > > > strings were HTML/XML and therefore needed escaping when,
> in
> > > >>> reality,
> > > >>> > > > > they were JS strings.
> >
> > > >>> > > > > If we had a review board, would you have opposed to this
> change?
> >
> > > >>> > > > > Massimo
> >
> > > >>> > > > > On Jul 23, 5:28 pm, Thadeus Burgess <thade...@thadeusb.com
> >
> > > >>> wrote:
> > > >>> > > > > > I also agree that this is a break in backwards
> compatibility.
> > > >>> It is
> > > >>> > > also
> > > >>> > > > > a
> > > >>> > > > > > change that was never considered for longer than 15
> minutes
> > > >>> before
> > > >>> > > the
> > > >>> > > > > > decision to make the change was implemented.
> >
> > > >>> > > > > > I really wish we would put certain things such as this
> under a
> > > >>> review
> > > >>> > > > > board
> > > >>> > > > > > so they don't get into web2py and break things!
> >
> > > >>> > > > > > --
> > > >>> > > > > > Thadeus
> >
> > > >>> > > > > > On Fri, Jul 23, 2010 at 2:33 PM, MikeEllis <
> > > >>> > > michael.f.el...@gmail.com
> > > >>> > > > > >wrote:
> >
> > > >>> > > > > > > Typo: 2 sentence in prior message should read
> >
> > > >>> > > > > > > " ... after XML() supplies the unescaped string."
> >
> > > >>> > > > > > > On Jul 23, 3:28 pm, Michael Ellis <
> michael.f.el...@gmail.com
> >
> > > >>> > > wrote:
> > > >>> > > > > > > > Urgh!  FWIW, putting XML() around the strings doesn't
> seem
> > > >>> to
> > > >>> > > work.
> > > >>> > > > > > >  Looks
> > > >>> > > > > > > > like the escaping is applied after XML() supplies the
> > > >>> unquoted
> > > >>> > > > > string.
> >
> > > >>> > > > > > > > I tried
> > > >>> > > > > > > > {{
> > > >>> > > > > > > > for optstring in (schartoptions, countpieoptions,
> > > >>> cchartoptions):
> > > >>> > > > > > > >     optstring = XML(optstring)
> > > >>> > > > > > > >     debug("opstring=%s"%optstring)
> > > >>> > > > > > > >     pass}}
> >
> > > >>> > > > > > > > after assigning the strings and before they are used
> in
> > > >>> inside
> > > >>> > > the
> > > >>> > > > > > > <script>
> > > >>> > > > > > > > tags.
> >
> > > >>> > > > > > > > The debug() calls show the strings with the single
> quotes
> > > >>> > > unescaped,
> > > >>> > > > > but
> > > >>> > > > > > > > they still end up being escaped in what gets sent to
> > > >>> browser.
> >
> > > >>> > > > > > > > On Fri, Jul 23, 2010 at 2:16 PM, Michael Ellis <
> > > >>> > > > > > > michael.f.el...@gmail.com>wrote:
> >
> > > >>> > > > > > > > > Thanks, Nathan. That's certainly a possibility.
>  It's
> > > >>> just that
> > > >>> > > I'm
> > > >>> > > > > not
> > > >>> > > > > > > > > sure what security issue this change actually
> fixes.
> > > >>>  There are
> > > >>> > > no
> > > >>> > > > > > > > > user-supplied strings in what I'm using to generate
> the
> > > >>> jQuery
> > > >>> > > > > calls.
> > > >>> > > > > > >  If
> > > >>> > > > > > > > > that were the case, then yes it would definitely be
> my
> > > >>> > > > > responsibility
> > > >>> > > > > > > to
> > > >>> > > > > > > > > properly sanitize it.
> >
> > > >>> > > > > > > > > Have to say this feels like a loss of  backward
> > > >>> compatibility
> > > >>> > > to
> > > >>> > > > > me.
> > > >>> > > > > > >  I've
> > > >>> > > > > > > > > got a fair amount of code in this app that uses
> that
> > > >>> technique;
> > > >>> > > > > it's
> > > >>> > > > > > > already
> > > >>> > > > > > > > > inherently messy because of the indirection
> involved in
> > > >>> code
> > > >>> > > > > > > generation.
> > > >>> > > > > > > > >  Wrapping it all in XML calls just adds to the
> mess.
> > > >>>  Hope
> > > >>> > > there's
> > > >>> > > > > a
> > > >>> > > > > > > way to
> > > >>> > > > > > > > > refine the security fix so that it's confined to
> the
> > > >>> areas that
> > > >>> > > > > matter.
> >
> > > >>> > > > > > > > > Cheers,
> > > >>> > > > > > > > > Mike
> >
> > > >>> > > > > > > > > On Fri, Jul 23, 2010 at 1:56 PM, mr.freeze <
> > > >>> > > nat...@freezable.com>
> > > >>> > > > > > > wrote:
> >
> > > >>> > > > > > > > >> It was probably introduced as a security fix. You
> can
> > > >>> do:
> > > >>> > > > > > > > >> {{
> > > >>> > > > > > > > >> schartoptions = XML("""{
> > > >>> > > > > > > > >>     type: 'bar',
> > > >>> > > > > > > > >>    barColor: 'green',
> > > >>> > > > > > > > >>    chartRangeMin: '%d',
> > > >>> > > > > > > > >>    chartRangeMax: '%d'
> > > >>> > > > > > > > >>    }
> > > >>> > > > > > > > >>    """%(chartmin,chartmax))
> > > >>> > > > > > > > >> }}
> >
> > > >>> > > > > > > > >> and it won't be escaped.
> >
> > > >>> > > > > > > > >> On Jul 23, 12:39 pm, Michael Ellis <
> > > >>> michael.f.el...@gmail.com
> >
> > > >>> > > > > wrote:
> > > >>> > > > > > > > >> > I've got an app with views that
> >
> > ...
> >
> > read more ยป

Reply via email to