Django

Code

Ticket #5768 (new)

Opened 1 year ago

Last modified 1 week ago

Allow QuerySet.values() to return values spanning joins (for multi-valued relations)

Reported by: anonymous <tobutaz+bugs@gmail.com> Assigned to:
Milestone: Component: Database layer (models, ORM)
Version: 0.96 Keywords:
Cc: trevor@caira.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

I'd like to write:

class Tag(models.Model):
    name = models.CharField(maxlength=50)

class Thing(models.Model):
    tags = models.ManyToManyKey(Tag)

Thing.objects.filter(tags__name).values('tags.name').distinct()

My use case is slightly more complicated (I use django-tagging and the GenericRelation? does not make things simpler).

Of course I could do it manually with a loop, but it is necessary to have a queryset for some things, such as using a generic view.

Attachments

Change History

10/17/07 05:50:29 changed by anonymous <tobutaz+bugs@gmail.com>

  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

Here is the use case with django-tagging:

    e_t = ContentType.objects.get_for_model(Entity)
    q_s = TaggedItem.objects.filter(content_type=e_t).extra(tables=['tag'], where=['tagged_item.tag_id=tag.id']).values('tag__name__exact').distinct()

10/19/07 05:50:14 changed by mtredinnick

  • keywords set to qs-rf.
  • stage changed from Unreviewed to Accepted.

Probably not a completely crazy idea and not too hard to do in queryset-refactor now.

10/20/07 10:40:51 changed by mtredinnick

  • component changed from Uncategorized to Database wrapper.

12/09/07 01:49:53 changed by mtredinnick

  • keywords deleted.

I've marked #3358 as a duplicate of this. We can implement it eventually, but probably not as part of the queryset-refactor work, since it's not really a show-stopper at the moment.

A couple of thoughts on the implementation:

  1. we should use foo__bar as the format for specifying the names, so that it's consistent with filtering and the new cross-model order_by() syntax.
  2. If we allow many-to-many or reverse one-to-many relations to be specified, we should restrict it to a maximum of one such relation in each values() call. The problem here is one of efficiency: if relation 1 has n1 rows and relation 2 has n2 rows in their result sets, doing a single, non-union query will result in n1*n2 rows being returned. Not cool if n1 and n2 are something like 100 each. If we do a union query, it's not more efficient than doing two separate queries, except we'll have to pay some computation penalty inside Django every time to work out when this is needed. So we don't permit that and the few cases where it's needed can be done with separate queries and dictionary updates.

So I'm going to remove the qs-rf keyword, but any patch for this should wait until after that branch is merged, since it will touch stuff that bears no resemblance to the current trunk code.

12/25/07 01:57:08 changed by trevor

  • cc set to trevor@caira.com.

02/13/08 01:19:15 changed by dogada

  • owner changed from nobody to dogada.
  • status changed from new to assigned.

02/14/08 04:56:15 changed by dogada

  • status changed from assigned to closed.
  • has_patch set to 1.
  • resolution set to fixed.

Support of related models in QuerySet?.values() was implemented as part of ticket #5420. See following patch: http://code.djangoproject.com/attachment/ticket/5420/queryset_fields_trunk.diff

Patch changes signature of this method from values(*fields) to values(*fields, **related_fields) but the change is backward compatible.

See more details about this patch at: http://www.mysoftparade.com/blog/django_orm_performance_patch/

02/14/08 05:26:19 changed by mtredinnick

  • status changed from closed to reopened.
  • resolution deleted.

This isn't fixed. A ticket is fixed when code for it has been committed to the appropriate branch in subversion.

Also, this isn't related to #5420 (your approach there is mixing multiple things). Reopening.

02/14/08 05:40:53 changed by mtredinnick

Also, for anybody working on this, please see the end of comment 4: patches should either be against queryset-refactor or wait until after that is merged into trunk. The current ValuesQuerySet implementation is quite different in the new code.

02/14/08 10:31:17 changed by dogada

  • owner deleted.
  • status changed from reopened to new.

03/12/08 07:41:58 changed by mtredinnick

(In [7230]) queryset-refactor: Refactored the way values() works so that it works properly across inherited models.

Completely by accident, this also allows values() queries to include fields from related models, providing it is crossing a single-valued relation (one-to-one, many-to-one). Many-to-many values() fields still aren't supported, since that requires actual thinking. So this refs #5768.

10/05/08 21:09:10 changed by mtredinnick

  • summary changed from Allow QuerySet.values() to return values spanning joins. to Allow QuerySet.values() to return values spanning joins (for multi-valued relations).

Add/Change #5768 (Allow QuerySet.values() to return values spanning joins (for multi-valued relations))




Change Properties
Action