When a FileField has a callable default value, the following error is
raised when a new object is created using a form and no value is provided
for the field:
`'function' object has no attribute '_committed' in
db/models/fields/files.py in pre_save, line 316`
This bug can be reproduced with the content of the following gist :
https://gist.github.com/ymph/cd2b684f3f2f38a680d5 and by following the
instruction in the README.
The problem does not appear when creating the object without forms.
I was able to naively "correct" the problem by adding the following lines
in the file db/models/fields/files.py, line 194 in FieldFile.!__get!__:
{{{
if callable(file):
file = file()
}}}
here is a complete traceback:
{{{
Environment:
Request Method: POST
Request URL: http://localhost:8000/admin/testdefault/testobject/add/
Django Version: 1.8.1
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'testdefault')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request,
*callback_args, **callback_kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/contrib/admin/options.py" in wrapper
616. return self.admin_site.admin_view(view)(*args,
**kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/utils/decorators.py" in _wrapped_view
110. response = view_func(request, *args, **kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/contrib/admin/sites.py" in inner
233. return view(request, *args, **kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/contrib/admin/options.py" in add_view
1516. return self.changeform_view(request, None, form_url,
extra_context)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/utils/decorators.py" in _wrapper
34. return bound_func(*args, **kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/utils/decorators.py" in _wrapped_view
110. response = view_func(request, *args, **kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/utils/decorators.py" in bound_func
30. return func.__get__(self, type(self))(*args2,
**kwargs2)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/utils/decorators.py" in inner
145. return func(*args, **kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/contrib/admin/options.py" in changeform_view
1467. self.save_model(request, new_object, form, not
add)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/contrib/admin/options.py" in save_model
1078. obj.save()
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/base.py" in save
710. force_update=force_update,
update_fields=update_fields)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/base.py" in save_base
738. updated = self._save_table(raw, cls, force_insert,
force_update, using, update_fields)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/base.py" in _save_table
822. result = self._do_insert(cls._base_manager, using,
fields, update_pk, raw)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/base.py" in _do_insert
861. using=using, raw=raw)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/manager.py" in manager_method
127. return getattr(self.get_queryset(), name)(*args,
**kwargs)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/query.py" in _insert
920. return
query.get_compiler(using=using).execute_sql(return_id)
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in execute_sql
970. for sql, params in self.as_sql():
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in as_sql
928. for obj in self.query.objs
File "/Users/ymh/dev/venvs/testdefault/lib/python2.7/site-
packages/django/db/models/fields/files.py" in pre_save
316. if file and not file._committed:
Exception Type: AttributeError at /admin/testdefault/testobject/add/
Exception Value: 'function' object has no attribute '_committed'
}}}
regards.
--
Ticket URL: <https://code.djangoproject.com/ticket/24823>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Old description:
New description:
Hello,
When a FileField has a callable default value, the following error is
raised when a new object is created using a form and no value is provided
for the field:
`'function' object has no attribute '_committed' in
db/models/fields/files.py in pre_save, line 316`
This bug can be reproduced with the content of the following gist :
https://gist.github.com/ymph/cd2b684f3f2f38a680d5 and by following the
instruction in the README.
The problem does not appear when creating the object without forms.
I was able to naively "correct" the problem by adding the following lines
in the file db/models/fields/files.py, line 194 in
FileDescriptor.!__get!__:
regards.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:1>
Comment (by ymph):
Hello,
a attempt for a correction can be found in the branch ticket_24823 of my
fork : https://github.com/IRI-Research/django/tree/ticket_24823
regards,
ymph
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:2>
* status: new => closed
* resolution: => needsinfo
Comment:
Currently the behavior of how `default` should work on `FileField` isn't
well defined (see #17224). Let's address that one first and then reopen
this if we decide it makes sense to support this. By the way, any patch
should be against the master branch, as this wouldn't be backported to
1.8. Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:3>
Comment (by Tai Lee):
Just spent a few hours stepping through tracebacks trying to find out
exactly what Django is doing here, before coming to the conclusion that it
must be a Django bug and searching for an existing ticket.
Perhaps I haven't read the documentation recently or thoroughly enough,
but they don't seem that ambiguous regarding the behaviour of `default`
specifically:
{{{
The default value for the field. This can be a value or a callable object.
If callable it will be called every time a new object is created.
}}}
There's no special caveat for `FileField` and `ImageField` saying that
callables cannot be used.
Whether or not additional special handling of the evaluated default value
(as per discussion on #17224) is ever implemented, that should not make
any difference at all as to whether or not a callable can be used as a
default.
I think this ticket should be re-opened, and can and should be resolved
much quicker and simpler than #17224, without much debate?
It's valid to assign a string to a `FileField` (on an instance, or as a
default value). Is there any reason why a callable that returns a string
shouldn't be valid?
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:4>
* status: closed => new
* resolution: needsinfo =>
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:5>
* keywords: FileField, models, field => FileField, models, field,
callable, default, form
Comment:
Plus, the fact that this actually does work as expected for `FileField`
(models) is *only* broken with forms, makes the case stronger that this is
a clear bug. The forms docs even say (of `Field.initial`):
{{{
Instead of a constant, you can also pass any callable
}}}
And when we stepped through form cleaning, we noticed that form data *did*
contain a properly evaluated default as `initial-{fieldname}`, but the
field cleaning ignored it and assigned the raw callable from the model
instead.
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:6>
* cc: real.human@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:7>
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/24823#comment:8>