#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.

Reply via email to