Code

#20927 closed Bug (wontfix)

Include known related fields for subclassed "QuerySet.only"

Reported by: lvo@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.5
Severity: Normal Keywords: queryset, only, related manager, manager
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have a model like these:

class PNRSegment(models.Model):
    pnr = models.ForeignKey('booking.PassengerNameRecord', related_name="segments")
    arrival_datetime = models.DateTimeField()

    objects = PNRSegmentManager()

Also i wrote my own Manager with own QuerySet:

class PNRSegmentManager(models.Manager):
    use_for_related_fields = True

    def get_query_set(self):
        return PNRSegmentQuerySet(self.model, using=self._db)

    def latest_datetime(self):
        return self.get_query_set().latest_datetime()


class PNRSegmentQuerySet(QuerySet):
    def latest_datetime(self):
        try:
            return self.order_by('-arrival_datetime')[0].arrival_datetime
        except IndexError:
            return None

I noticed that QuerySet.only has strange behavior:

# When launching pdb into PNRSegmentQuerySet.latest_datetime:
(Pdb) pp self
[<PNRSegment: PNRSegment object>, <PNRSegment: PNRSegment object>]
(Pdb) pp self.count()
2
(Pdb) pp self[0]
<PNRSegment: PNRSegment object>
(Pdb) pp self.only('arrival_datetime').count()
2
(Pdb) pp self.only('arrival_datetime')[0]
*** IndexError: IndexError(("PNRSegment matching query does not exist. Lookup parameters were {'pk': None}",),)

After tracing of QuerySet.clone i found my error: when subclassing QuerySet for related manager, each QuerySet.only call should contain related field:

(Pdb) pp self.only('arrival_datetime', 'pnr')[0]
<PNRSegment_Deferred_airline_code_class_code_ ... cutted ...>

I think that this is not obvious behaviour. QuerySet.only should authomatically include all fields from QuerySet._known_related_objects.

Attachments (0)

Change History (4)

comment:1 Changed 10 months ago by sduveen

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

only() is about the fields returned. It's specifically used to limit fields and you use it so that it won't include additional ones. If you want defaults, then don't use only()

comment:2 Changed 10 months ago by sduveen

  • Resolution invalid deleted
  • Status changed from closed to new

seeing if we can make a useful test

comment:3 Changed 10 months ago by sduveen

seems to be working in 1.6 and master.

This test shows we can do a query that has a manager and foreignkey object.
https://github.com/schuyler1d/django/commit/047c131bc96a844d2769f3a4c5612119330413a1

comment:4 Changed 10 months ago by sduveen

  • Resolution set to wontfix
  • Status changed from new to closed

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.