#29893: Unexpected behavior of DetailView on a model defining __len__() returning False -----------------------------------------+------------------------ Reporter: burrscurr | Owner: nobody Type: Bug | Status: new Component: Generic views | Version: 2.1 Severity: Normal | Keywords: Triage Stage: Unreviewed | Has patch: 1 Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | -----------------------------------------+------------------------ == Description
When using Django's DetailView on a model defining a {{{__len__()}}} method, the model object is not always added to context. This is the case, when {{{__len__()}}} of the model object returns zero. The behavior is caused by {{{BaseDetailView.get()}}} calling {{{SingleObjectMixin.get_context_data()}}} which checks like this, if {{{self.object}}} was set before by{{{SingleObjectMixin.get_object()}}}: {{{ if self.object: # adds self.object to context }}} Because this check is happening implicitly and not against {{{None}}}, pythons default implementation calling {{{self.object.__len__()}}} ([https://docs.python.org/3/library/stdtypes.html#truth-value-testing]) causes this condition to evaluate to False, at least if {{{__len__()}}} returns zero. This leads to not having the wanted object in context data. == Steps to reproduce: Create an empty model defining a {{{__len__}}} method returning zero and a DetailView like this: {{{ class TestModel(models.Model): def __len__(self): return 0 class TestModelDetailView(DetailView): model = TestModel template_name = 'test.html' # some template }}} After creating a TestModel object, the described behavior can be reproduced when calling the Detailview (url pattern like this {{{/test/<int:pk>/}}}). == Proposed solution Simply checking if self.object is the default value None prevents this not easy to find bug. {{{SingleObjectMixin.get_queryset()}}} also has a similar check {{{ if self.model: # some action }}} which does not seem to cause problems, because {{{self.model}}} is a class and no object. It should be considered to also check against the default value for self.model here, which is None. -- Ticket URL: <https://code.djangoproject.com/ticket/29893> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/052.ca2801270d3f27b30fa1ecdec36888fa%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.