This is interesting.  I think the two examples you give are distinct
use cases and they should be.  But I think it's just as common to want
to do what felix is doing.  Essentially he wants to modify a queryset
as it exists by adding or overriding additional parameters.  It can be
very convenient to build this up as you go through the logic in your
app.  Felix ends up doing this manually by just holding all of his
params in a dict and adding them at the end.  But would it be a bad
thing for django to support this use case out of the box?  How about
something like

   Queryset.update(dict | **kwargs)

so this

   qs = Model.objects.filter(a__b=x)
   qs = qs.update(a__c=y)

Is equivalent to

   Model.objects.filter(a__b=x, a__c=y)

It would still return a new query set to support chaining.  But the
new one would be built with a merging the of the old and new
parameters rather than a "filter these and then filter these" type of
structure.

The name "update" conflicts with the api for dict.update which updates
in place.  Maybe that's okay or maybe it needs a new name.

:Marco

On Feb 22, 3:15 am, Russell Keith-Magee <freakboy3...@gmail.com>
wrote:
> On Mon, Feb 22, 2010 at 4:48 AM, felix <crucialfe...@gmail.com> wrote:
>
> > This seems so blatant that it couldn't really be a bug without someone
> > noticing. Django 1.2
>
> >        qs = Apt.objects.filter(list_on_web=True,is_available=True)
>
> >         # FastAdderStatus has Apt and Service as fk
> >        qs = qs.filter(fastadderstatus__service=self.service)
>
> >        # later on here's another filter on the same table
> >        qs = qs.filter(fastadderstatus__running_status__in= (2, 3, 4))
>
> > produces this:
>
> >  SELECT U0."id" FROM "nsproperties_apt" U0 INNER JOIN
> > "fastadder_fastadderstatus" U1 ON (U0."id" = U1."apt_id") INNER JOIN
> > "fastadder_fastadderstatus" U3 ON (U0."id" = U3."apt_id") WHERE
> > (U0."list_on_web" = True  AND U0."is_available" = True  AND
> > U1."service_id" = 4  AND U3."running_status" IN (2, 3, 4))
>
> > Note that it joins the same table twice, and the Apt is not returning
> > distinct.  Postgres is not liking the query.
>
> > count: 2837
>
> > [<Apt: Property #12297>, <Apt: Property #12297>, <Apt: Property
> > #12297>, <Apt: Property #12304>, <Apt: Property #12304>, <Apt:
> > Property #12304>, <Apt: Property #12305>, <Apt: Property #12305>,
> > <Apt: Property #12305>, <Apt: Property #12308>, <Apt: Property
> > #12308>, <Apt: Property #12308>, <Apt: Property #12309>, <Apt:
> > Property #12309>, <Apt: Property #12309>, <Apt: Property #12311>,
> > <Apt: Property #12311>, <Apt: Property #12311>, <Apt: Property
> > #12314>, <Apt: Property #12314>, '...(remaining elements
> > truncated)...']
>
> > what it should say (manually fixed) :
>
> >  SELECT U0."id" FROM "nsproperties_apt" U0 INNER JOIN
> > "fastadder_fastadderstatus" U1 ON (U0."id" = U1."apt_id") WHERE
> > (U0."list_on_web" = True  AND U0."is_available" = True  AND
> > U1."service_id" = 4  AND U1."running_status" IN (2, 3, 4))
>
> > count: 611, no dups
>
> > My solution:
>
> >        params = {}
> >        if self.service:
> >            params['fastadderstatus__service'] = self.service
> >        if self.agent:
> >            params['agents'] = self.agent
>
> >        if self.status:
>
> > params.update( 
> > FastAdderStatus.objects.filter_params_for_status(self.status,'fastadderstat 
> > us') )
>
> >        # a single call to filter
> >        qs = qs.filter(**params)
>
> > which avoids the (?) bug and also is vastly more efficient.
>
> You haven't found a bug - Django is returning exactly what you asked
> for. There is a difference between making the query:
>
> Model.objects.filter(a__b=x).filter(a__c=y)
>
> and the query:
>
> Model.objects.filter(a__b=x, a__c=y).
>
> In the first query, Django will use two different joins on the 'A'
> table. In the second query, the join on 'A' will be reused. It sounds
> like what you want is the second query.
>
> This behaviour is documented here [1].
>
> [1]http://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-mult...
>
> Yours,
> Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@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