Opened 3 years ago

Closed 3 years ago

#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


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):
            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()
(Pdb) pp self[0]
<PNRSegment: PNRSegment object>
(Pdb) pp self.only('arrival_datetime').count()
(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.

Change History (4)

comment:1 Changed 3 years 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 3 years ago by sduveen

  • Resolution invalid deleted
  • Status changed from closed to new

seeing if we can make a useful test

comment:3 Changed 3 years 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.

comment:4 Changed 3 years ago by sduveen

  • Resolution set to wontfix
  • Status changed from new to closed
Note: See TracTickets for help on using tickets.
Back to Top