2011-05-19 11:36:55 +04:00
# """
# ..
# >>> from djangorestframework.parsers import FormParser
# >>> from djangorestframework.compat import RequestFactory
2011-05-24 13:27:24 +04:00
# >>> from djangorestframework.views import View
2011-05-19 11:36:55 +04:00
# >>> from StringIO import StringIO
# >>> from urllib import urlencode
# >>> req = RequestFactory().get('/')
2011-05-24 13:27:24 +04:00
# >>> some_view = View()
2011-05-19 11:36:55 +04:00
# >>> some_view.request = req # Make as if this request had been dispatched
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# FormParser
# ============
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# Data flatening
# ----------------
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# Here is some example data, which would eventually be sent along with a post request :
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> inpt = urlencode([
# ... ('key1', 'bla1'),
# ... ('key2', 'blo1'), ('key2', 'blo2'),
# ... ])
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# Default behaviour for :class:`parsers.FormParser`, is to return a single value for each parameter :
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> (data, files) = FormParser(some_view).parse(StringIO(inpt))
# >>> data == {'key1': 'bla1', 'key2': 'blo1'}
# True
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# However, you can customize this behaviour by subclassing :class:`parsers.FormParser`, and overriding :meth:`parsers.FormParser.is_a_list` :
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> class MyFormParser(FormParser):
2011-12-29 17:31:12 +04:00
# ...
2011-05-19 11:36:55 +04:00
# ... def is_a_list(self, key, val_list):
# ... return len(val_list) > 1
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# This new parser only flattens the lists of parameters that contain a single value.
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> (data, files) = MyFormParser(some_view).parse(StringIO(inpt))
# >>> data == {'key1': 'bla1', 'key2': ['blo1', 'blo2']}
# True
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# .. note:: The same functionality is available for :class:`parsers.MultiPartParser`.
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# Submitting an empty list
# --------------------------
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# When submitting an empty select multiple, like this one ::
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# <select multiple="multiple" name="key2"></select>
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# The browsers usually strip the parameter completely. A hack to avoid this, and therefore being able to submit an empty select multiple, is to submit a value that tells the server that the list is empty ::
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# <select multiple="multiple" name="key2"><option value="_empty"></select>
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# :class:`parsers.FormParser` provides the server-side implementation for this hack. Considering the following posted data :
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> inpt = urlencode([
# ... ('key1', 'blo1'), ('key1', '_empty'),
# ... ('key2', '_empty'),
# ... ])
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# :class:`parsers.FormParser` strips the values ``_empty`` from all the lists.
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> (data, files) = MyFormParser(some_view).parse(StringIO(inpt))
# >>> data == {'key1': 'blo1'}
# True
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# Oh ... but wait a second, the parameter ``key2`` isn't even supposed to be a list, so the parser just stripped it.
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# >>> class MyFormParser(FormParser):
2011-12-29 17:31:12 +04:00
# ...
2011-05-19 11:36:55 +04:00
# ... def is_a_list(self, key, val_list):
# ... return key == 'key2'
2011-12-29 17:31:12 +04:00
# ...
2011-05-19 11:36:55 +04:00
# >>> (data, files) = MyFormParser(some_view).parse(StringIO(inpt))
# >>> data == {'key1': 'blo1', 'key2': []}
# True
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# Better like that. Note that you can configure something else than ``_empty`` for the empty value by setting :attr:`parsers.FormParser.EMPTY_VALUE`.
# """
# import httplib, mimetypes
# from tempfile import TemporaryFile
# from django.test import TestCase
# from djangorestframework.compat import RequestFactory
# from djangorestframework.parsers import MultiPartParser
2011-05-24 13:27:24 +04:00
# from djangorestframework.views import View
2011-05-19 11:36:55 +04:00
# from StringIO import StringIO
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# def encode_multipart_formdata(fields, files):
# """For testing multipart parser.
# fields is a sequence of (name, value) elements for regular form fields.
# files is a sequence of (name, filename, value) elements for data to be uploaded as files
# Return (content_type, body)."""
# BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
# CRLF = '\r\n'
# L = []
# for (key, value) in fields:
# L.append('--' + BOUNDARY)
# L.append('Content-Disposition: form-data; name="%s"' % key)
# L.append('')
# L.append(value)
# for (key, filename, value) in files:
# L.append('--' + BOUNDARY)
# L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
# L.append('Content-Type: %s' % get_content_type(filename))
# L.append('')
# L.append(value)
# L.append('--' + BOUNDARY + '--')
# L.append('')
# body = CRLF.join(L)
# content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
# return content_type, body
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
# def get_content_type(filename):
# return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
2011-12-29 17:31:12 +04:00
#
2011-05-19 11:36:55 +04:00
#class TestMultiPartParser(TestCase):
# def setUp(self):
# self.req = RequestFactory()
# self.content_type, self.body = encode_multipart_formdata([('key1', 'val1'), ('key1', 'val2')],
# [('file1', 'pic.jpg', 'blablabla'), ('file1', 't.txt', 'blobloblo')])
#
# def test_multipartparser(self):
# """Ensure that MultiPartParser can parse multipart/form-data that contains a mix of several files and parameters."""
# post_req = RequestFactory().post('/', self.body, content_type=self.content_type)
2011-05-24 13:27:24 +04:00
# view = View()
2011-05-19 11:36:55 +04:00
# view.request = post_req
# (data, files) = MultiPartParser(view).parse(StringIO(self.body))
# self.assertEqual(data['key1'], 'val1')
# self.assertEqual(files['file1'].read(), 'blablabla')
2011-03-11 16:05:35 +03:00
2011-06-09 19:24:27 +04:00
from StringIO import StringIO
from django import forms
from django . test import TestCase
from djangorestframework . parsers import FormParser
2011-12-11 22:27:40 +04:00
from djangorestframework . parsers import XMLParser
import datetime
2011-06-09 19:24:27 +04:00
2012-02-25 22:45:17 +04:00
2011-06-09 19:24:27 +04:00
class Form ( forms . Form ) :
field1 = forms . CharField ( max_length = 3 )
field2 = forms . CharField ( )
2012-02-25 22:45:17 +04:00
2011-06-09 19:24:27 +04:00
class TestFormParser ( TestCase ) :
def setUp ( self ) :
2011-12-29 17:31:12 +04:00
self . string = " field1=abc&field2=defghijk "
2011-06-09 19:24:27 +04:00
def test_parse ( self ) :
""" Make sure the `QueryDict` works OK """
2012-02-25 23:02:26 +04:00
parser = FormParser ( )
2011-12-29 17:31:12 +04:00
2011-06-09 19:24:27 +04:00
stream = StringIO ( self . string )
2012-08-28 18:46:38 +04:00
( data , files ) = parser . parse ( stream )
2011-06-09 19:24:27 +04:00
self . assertEqual ( Form ( data ) . is_valid ( ) , True )
2011-12-11 22:27:40 +04:00
2012-02-25 22:45:17 +04:00
2011-12-11 22:27:40 +04:00
class TestXMLParser ( TestCase ) :
def setUp ( self ) :
2012-01-13 13:11:34 +04:00
self . _input = StringIO (
2011-12-11 22:27:40 +04:00
' <?xml version= " 1.0 " encoding= " utf-8 " ?> '
' <root> '
' <field_a>121.0</field_a> '
' <field_b>dasd</field_b> '
2012-02-25 22:45:17 +04:00
' <field_c></field_c> '
2011-12-11 22:27:40 +04:00
' <field_d>2011-12-25 12:45:00</field_d> '
' </root> '
2012-02-25 22:45:17 +04:00
)
self . _data = {
2011-12-11 22:27:40 +04:00
' field_a ' : 121 ,
2012-02-25 22:45:17 +04:00
' field_b ' : ' dasd ' ,
2011-12-11 22:27:40 +04:00
' field_c ' : None ,
' field_d ' : datetime . datetime ( 2011 , 12 , 25 , 12 , 45 , 00 )
}
2012-01-13 13:11:34 +04:00
self . _complex_data_input = StringIO (
' <?xml version= " 1.0 " encoding= " utf-8 " ?> '
' <root> '
' <creation_date>2011-12-25 12:45:00</creation_date> '
' <sub_data_list> '
' <list-item><sub_id>1</sub_id><sub_name>first</sub_name></list-item> '
' <list-item><sub_id>2</sub_id><sub_name>second</sub_name></list-item> '
' </sub_data_list> '
' <name>name</name> '
' </root> '
2012-02-25 22:45:17 +04:00
)
2012-01-13 13:11:34 +04:00
self . _complex_data = {
2012-02-25 22:45:17 +04:00
" creation_date " : datetime . datetime ( 2011 , 12 , 25 , 12 , 45 , 00 ) ,
" name " : " name " ,
2012-01-13 13:11:34 +04:00
" sub_data_list " : [
{
2012-02-25 22:45:17 +04:00
" sub_id " : 1 ,
2012-01-13 13:11:34 +04:00
" sub_name " : " first "
2012-02-25 22:45:17 +04:00
} ,
2012-01-13 13:11:34 +04:00
{
2012-02-25 22:45:17 +04:00
" sub_id " : 2 ,
2012-01-13 13:11:34 +04:00
" sub_name " : " second "
}
]
2012-02-25 22:45:17 +04:00
}
2012-01-13 13:11:34 +04:00
2011-12-11 22:27:40 +04:00
def test_parse ( self ) :
2012-02-25 23:02:26 +04:00
parser = XMLParser ( )
2012-08-28 18:46:38 +04:00
( data , files ) = parser . parse ( self . _input )
2012-01-13 13:11:34 +04:00
self . assertEqual ( data , self . _data )
def test_complex_data_parse ( self ) :
2012-02-25 23:02:26 +04:00
parser = XMLParser ( )
2012-08-28 18:46:38 +04:00
( data , files ) = parser . parse ( self . _complex_data_input )
2012-01-13 13:11:34 +04:00
self . assertEqual ( data , self . _complex_data )