tutorial/example of multipart/form-data

6,207 views
Skip to first unread message

Andrew Smolik

unread,
Nov 11, 2012, 5:21:55 PM11/11/12
to django-res...@googlegroups.com
Hi,

I'm new to django-rest-framework and I'm having a hard time figuring out how to upload a file via the api. I've done a lot of searching on google but there are no examples. Is it possible to create a multipart/form-data example and post it to github? It would be greatly appreciated.

Thanks,

Andrew

Tom Christie

unread,
Nov 12, 2012, 3:31:07 PM11/12/12
to django-res...@googlegroups.com
Hi Andrew,

  What language is your client written in?

As a starter for trying out how multipart file upload works, use this simple view,
and throw some requests at it using curl and/or python requests.

    @api_view(['POST'])
    def upload_api_view(request):
        return Response({'data': request.DATA, 'files': request.FILES)


Play around with that and make sure it all makes sense.
There's no FileField/ImageField support yet, so you'll need to write the view to handle the upload yourself.


Cheers,

  Tom

Andrew Smolik

unread,
Nov 18, 2012, 9:05:11 AM11/18/12
to django-res...@googlegroups.com
Hi Tom,

Thank you for the information! I've been posting to the view below and I get a 200 but the file never uploads (I don't see it in the db or filesystem). If you have time, can you provide a more detail example? It would be greatly appreciated.

Thanks,

Andrew

Tom Christie

unread,
Nov 18, 2012, 3:43:17 PM11/18/12
to django-res...@googlegroups.com
The request.FILES property behaves just the same as it does with standard Django.

Cribbing some stuff from the docs: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/

You can deal with the uploaded file manually, eg...

@api_view(['POST'])
    def upload_file(request):
        handle_uploaded_file(request.FILES['file'])
        return Response('uploaded')

    def handle_uploaded_file(f):
        with open('some/file/name.txt', 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)

Use the UploadedFile to set the value of a FileField on a model, eg...

    @api_view(['POST'])
    def upload_file(request):
        instance = MyModelWithFileField(file_field=request.FILES['file'])
            instance.save()
            return Response('uploaded')

And, since Marko has just added support for FileFields and ImageFields (version 2.1.3), you can now also use the standard create and update generic views, or use a ModelSerializer for a model which includes a FileField or ImageField.

I would love to update the docs with some more complete examples at some point.  If you get what you want working and would consider contributing, please consider making a pull request to the documentation addressing whatever bits you think would be helpful to newcomers.

Cheers,

  t.

Andrew Smolik

unread,
Nov 26, 2012, 12:22:50 AM11/26/12
to django-res...@googlegroups.com
Hi,

Thanks for your help. I was able to get it working. I created a tutorial/example of the multipart/form-data with django-rest-framwork (https://github.com/ansother/multipart-form-data_django_rest_framework_tutorial). If you would like, in late december I can probably add it to the django-rest-framework website (this is my first time contributing to an open source project). 

Also, I think it would be helpful if you could add search to the django-rest-framework. It would make navigating the site much easier. 

Thanks again,

Andrew

greenhand

unread,
Dec 10, 2012, 5:02:12 AM12/10/12
to django-res...@googlegroups.com
I am new to python and DRF and thank you very much for the tutorial.
Unfortunately, I encounter an error when posting to api/upload_serializers/
The error message is:
 
TypeError at /api/upload_serializers/
object.__new__(cStringIO.StringO) is not safe, use cStringIO.StringO.__new__()
Request Method: POST
Request URL: api/upload_serializers/
Django Version: 1.4.2
Exception Type: TypeError
Exception Value: object.__new__(cStringIO.StringO) is not safe, use cStringIO.StringO.__new__()
 
Exception Location: /usr/lib/python2.7/copy_reg.py in __newobj__, line 93
Python Executable: /usr/bin/python
Python Version: 2.7.1
 
Does I miss something?
 
As for another question, what is the difference between these two APIs (/api/upload_form/ and /api/upload_serializers/)?

Andrew Smolik於 2012年11月26日星期一UTC+8下午1時22分50秒寫道:

Dwayne Ghant

unread,
Dec 18, 2012, 1:42:34 PM12/18/12
to django-res...@googlegroups.com
Hey Tom,

I tried to used Andrew's code that he build from you suggestions and I keep getting the error listed below: 

------------------------------------------------------------------------------------------------------------------------
Environment:


Request Method: POST

Django Version: 1.4.2
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "C:\Python27\lib\site-packages\django\views\generic\base.py" in view
  48.             return self.dispatch(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  77.         return view_func(*args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  363.             response = self.handle_exception(exc)
File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  360.             response = handler(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\decorators.py" in handler
  30.             return func(*args, **kwargs)
File "C:\Users\dghant\Documents\workspace-eclipse-jee-juno\PESC_webservice\PESC_webservice\views.py" in upload_form
  43.         instance = Files(docfile=request.FILES['file'], title=request.DATA['title'])
File "C:\Python27\lib\site-packages\rest_framework\request.py" in FILES
  159.             self._load_data_and_files()
File "C:\Python27\lib\site-packages\rest_framework\request.py" in _load_data_and_files
  190.             self._data, self._files = self._parse()
File "C:\Python27\lib\site-packages\rest_framework\request.py" in _parse
  274.         parsed = parser.parse(stream, media_type, self.parser_context)
File "C:\Python27\lib\site-packages\rest_framework\parsers.py" in parse
  137.             tree = ET.parse(stream)
File "C:\Python27\lib\xml\etree\ElementTree.py" in parse
  1183.     tree.parse(source, parser)
File "C:\Python27\lib\xml\etree\ElementTree.py" in parse
  656.                 parser.feed(data)
File "C:\Python27\lib\xml\etree\ElementTree.py" in feed
  1643.             self._raiseerror(v)
File "C:\Python27\lib\xml\etree\ElementTree.py" in _raiseerror
  1507.         raise err

Exception Type: ParseError at /upload_form/
Exception Value: syntax error: line 1, column 0
------------------------------------------------------------------------------------------------------------------------


Any assistance would greatly be appreciated. 

Dwayne Ghant

unread,
Dec 18, 2012, 1:44:54 PM12/18/12
to django-res...@googlegroups.com
Hey Andrew,

I follow you tutorial exactly the way you instructed and received the error below: 




Your help would be deeply appreciated. 

Andrew Smolik

unread,
Dec 19, 2012, 3:20:28 PM12/19/12
to django-res...@googlegroups.com
make sure these python packages are installed:
Django==1.4.2
Pygments==1.5
argparse==1.2.1
djangorestframework==2.1.6
wsgiref==0.1.2
requests==0.14.2
Markdown==2.2.0
dj-database-url==0.2.0


how are you making the post?


Andrew

IAmIT (Michel)

unread,
Dec 20, 2012, 9:15:05 AM12/20/12
to django-res...@googlegroups.com
Thanx Andrew, perfect example, exactly what I was looking for!
And thanx rest framework developers for the adding of the File and ImageFields to the serializer.... what a number of codelines this is saving me!

Op maandag 26 november 2012 06:22:50 UTC+1 schreef Andrew Smolik het volgende:

Tom Christie

unread,
Dec 20, 2012, 9:37:55 AM12/20/12
to django-res...@googlegroups.com
Hi Andrew, I just had a chance to look at this for the first time today - great stuff, very helpful!
If you do want to contribute some docs along these lines that'd be great.
I expect the docs would include a slimmed down version of this tut, and also a link to your repo for the full thing.

Thanks!

  Tom

Dwayne Ghant

unread,
Dec 22, 2012, 9:46:25 AM12/22/12
to django-res...@googlegroups.com
Thanks Andrew,

I will make sure that all these package are installed.  To answer your question, I use 'curl' for testing all my post.

Andrew Smolik

unread,
Dec 22, 2012, 2:38:50 PM12/22/12
to django-res...@googlegroups.com
You should try using the requests module in the example. I didn't test with curl. 

Thanks,

Andrew

Sent from my iPhone. Please excuse any typos. 

Andrew Smolik

unread,
Dec 22, 2012, 2:39:41 PM12/22/12
to django-res...@googlegroups.com
Sure. Do you have any example docs that I can model my docs off of?


Thanks,

Andrew

Sent from my iPhone. Please excuse any typos. 
Reply all
Reply to author
Forward
0 new messages