Pergunta

I need to get a file through a SOAP Web Service and save it into a model using django's FileField.

I've done the following:

In my SOAP Wrapper, I save the file in a temp directory

# ... get the file and file_name and decode put it into a variable called data
f = open('tmp/%s' % filename, 'w+')
f.write(data)
# build a dictionary with another useful metadata

Nothing strange here (i guess)

Then, in my view I do the following:

from django.core.files import File
for ext in extensions:
    messages = helpers.get_new_messages(ext)
    for msg in messages:
        vm = VoiceMessage()
        filename = '%s-%s' % (ext.t_account_name, msg['name'])
        vm.extension = ext 
        vm.origin = msg['origin']
        vm.date = msg['when']
        vm.message.save(filename, File(msg['file'])) # Error is raised here
        msg['file'].close()
        vm.save()

And I get the following error:

TypeError at /account/dashboard/messages/ expected string or buffer

I already tried this How to assign a local file to the FileField in Django?

and this Django - how to create a file and save it to a model's FileField?

Am I missing something?

EDIT APRIL 17th 2013: adding traceback

I debugged it and the type(msg['file']) call returned:

<type 'file'>

More specifically:

<open file './voice_message_2013-4-15_22-41-58.au', mode 'w+' at 0xca0fe40>

And here is the full traceback.

Internal Server Error: /account/dashboard/messages/
Traceback (most recent call last):
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/israelord/Work/4geeks/ringtu/ringtu/profiles/views.py", line 239, in account_dashboard_messages
    vm.message.save(filename, File(msg['file']))
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/fields/files.py", line 95, in save
    self.instance.save()
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/base.py", line 546, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/base.py", line 650, in save_base
    result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/manager.py", line 215, in _insert
    return insert_query(self.model, objs, fields, **kwargs)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/query.py", line 1673, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 936, in execute_sql
    for sql, params in self.as_sql():
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 894, in as_sql
    for obj in self.query.objs
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 304, in get_db_prep_save
    prepared=False)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 835, in get_db_prep_value
    value = self.get_prep_value(value)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 820, in get_prep_value
    value = self.to_python(value)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 788, in to_python
    parsed = parse_datetime(value)
  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/utils/dateparse.py", line 67, in parse_datetime
    match = datetime_re.match(value)
TypeError: expected string or buffer
Foi útil?

Solução

It looks like your issue is not with the FileField, but occurs when saving the VoiceMessage instance instead.

In the traceback, the failure occurs at the end of FieldFile.save():

  File "/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/db/models/fields/files.py", line 95, in save
    self.instance.save()

Which means that everything went fine there, and only when this method in turns call save() on the vm object does the problem arise:

# FileField.save() calls instance.save() just before returning
# Here, self.instance is the vm object
def save(self, name, content, save=True): 
    name = self.field.generate_filename(self.instance, name) 
    self.name = self.storage.save(name, content) 
    setattr(self.instance, self.field.name, self.name) 

    # Update the filesize cache 
    self._size = content.size 
    self._committed = True 

    # Save the object because it has changed, unless save is False 
    if save: 
        self.instance.save() 

My best guess is the problem is on vm.date or another DateTimeField field, as the exception is raised in DateTimeField.to_python function. Can you check the type of msg['when']? You can also confirm this by skipping the instance save step:

vm.message.save(filename, File(msg['file']), False) # Added False
msg['file'].close()
vm.save() # Error should now be raised here
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top