Condition: A model with a ForeignKey or OneToOne relationship to another model, where the related model instance may be null.
Desired Behavior: queryset.values() or values_list() returns all records from queryset, not just those with valid related model instance.
Observed Behavior: queryset.values() or values_list() returns records for only those members of the queryset where the related model instance exists
Django 1.8.6 Postgres 9.4.1
#!
class Release(Model):
release = TextField()
class Case(Model):
reference = TextField()
release = OneToOneField(Release, blank=True, null=True,
..........related_name='cases')
from models import Case
cases = Case.objects.all()
cases.count()
228
fieldnames = ['reference']
records = cases.values(*fieldnames)
records.count()
228
#So far, so good
fieldnames = ('reference','release__release')
records = cases.values(*fieldnames)
records.count()
63
#No, not good. Just lost a whole bunch of records, why?
cases = Case.objects.filter(release__isnull=False)
cases.count()
63
records = cases.values(*fieldnames)
records.count()
63
#Clearly this is because there is no related release for each missing case.
#As we see here:
case_without_release = Case.objects.filter(release__isnull=True)[0]
case.release
ReleatedObjectDoesNotExist: Case has no release
#How then to make queryset.values() or queryset.values_list() behave in the expected manner, by failing gracefully when it finds a member of a queryset to have a RelatedObjectDoesNotExist exception, and thus writing out the record to values() or values_list() the exception notwithstanding.
Thank you,
-Steve