Loading…

OMG I’ve found a bug in Django

Sometimes when working with Django, you encounter an exception that looks like a bug in Django. While creating an instance of MyModel with the Django admin, I encountered this beauty:

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/admin/my_app/my_model/1/

...

Traceback:
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
112. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
452. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
99. response = view_func(request, *args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
52. response = view_func(request, *args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
198. return view(request, *args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
29. return bound_func(*args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
99. response = view_func(request, *args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
25. return func(self, *args2, **kwargs2)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/db/transaction.py" in inner
371. return func(*args, **kwargs)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
1282. media = media + inline_admin_formset.media
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/contrib/admin/helpers.py" in _media
245. media = self.opts.media + self.formset.media
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/forms/formsets.py" in media
373. if self.forms:
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/utils/functional.py" in __get__
49. res = instance.__dict__[self.func.__name__] = self.func(instance)
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/forms/formsets.py" in forms
133. forms = [self._construct_form(i) for i in xrange(self.total_form_count())]
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/forms/formsets.py" in total_form_count
108. initial_forms = self.initial_form_count()
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/forms/models.py" in initial_form_count
844. return super(BaseInlineFormSet, self).initial_form_count()
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/forms/models.py" in initial_form_count
550. return len(self.get_queryset())
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/db/models/query.py" in __len__
77. self._fetch_all()
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/db/models/query.py" in _fetch_all
857. self._result_cache = list(self.iterator())
File "/Users/danielhepper/.virtualenvs/my_project/lib/python2.7/site-packages/django/db/models/query.py" in iterator
230. obj = model(*row_data)

Exception Type: TypeError at /admin/my_app/my_model/1/
Exception Value: __init__() takes exactly 1 argument (10 given)

There isn’t any mention of my code in the stack trace, so it must be Django’s fault, right?

Wrong! Look at the last line of the stack trace. Inspecting the variable model reveals that it refers to my one of my model classes. The model in question looked like this.

class MyNestedModel(models.Model):

    def __init__(self, **kwargs):
        ...
        super(MyNestedModel, self).__init__(**kwargs)

In this model, I had overwritten the constructor but didn’t add *args to accept arbitrary positional arguments. How does a bad constructor in MyNestedModel break the admin page for MyModel?

MyNestedModel has a foreign key to MyModel and the admin for MyModel displays the related MyNestedModelss as inline forms. In this case, Django uses positional arguments to create model instances.

Accepting and passing on the positional arguments fixed it.

class MyNestedModel(models.Model):

    def __init__(self, *args, **kwargs):
        ...
        super(MyNestedModel, self).__init__(*args, **kwargs)

Leave a Reply