QuerySets in Dictionaries
scoopseven
mark.kecko at gmail.com
Tue Nov 17 15:30:49 EST 2009
On Nov 14, 11:55 pm, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
> On Fri, 13 Nov 2009 14:10:10 -0800, scoopseven wrote:
> > I actually had a queryset that was dynamically generated, so I ended up
> > having to use the eval function, like this...
>
> > d = {}
> > for thing in things:
> > query_name = 'thing_' + str(thing.id)
> > query_string = 'Thing.objects.filter(type=' + str(thing.id) +
> > ').order_by(\'-date\')[:3]'
> > executable_string = query_name + ' = Thing.objects.filter
> > (type=' + str(thing.id) + ').order_by(\'-date\')[:3]'
> > exec(executable_string)
> > d[query_name] = eval(query_string)
>
> What an unmaintainable mess.
>
> If I've understood it, you can make it less crap by (1) getting rid of
> the unnecessary escaped quotes, (2) avoiding generating the same strings
> multiple times, and (3) avoiding string concatenation.
>
> d = {}
> for thing in things:
> expr = "Thing.objects.filter(type=%s).order_by('-date')[:3]"
> expr = rhs % thing.id
> name = "thing_%s" % thing.id
> exec("%s = %s" % (name, expr))
> d[name] = eval(expr)
>
> What else can we do to fix it? Firstly, why are you creating local
> variables "thing_XXX" (where XXX is the thing ID) *and* dictionary keys
> of exactly the same name? I'm sure you don't need the local variables.
> (If you think you do, you almost certainly don't.) That gets rid of the
> exec.
>
> Next, let's get rid of the eval:
>
> d = {}
> for thing in things:
> x = thing.id
> name = "thing_%s" % x
> d[name] = Thing.objects.filter(type=x).order_by('-date')[:3]
>
> About half the size, ten times the speed, and 1000 times the readability.
>
> Unless I've missed something, you don't need either exec or eval.
>
> --
> Steven
Steven,
This worked like a charm! Thank you for your insight, it's greatly
appreciated.
Mark
More information about the Python-list
mailing list