Controller Assignment Solution

Last modified: 05-14-2015

HeartBeat Response

The controller for this question is really simple - it’s just testing whether you understand the basic mechanism of controllers. The reference source code is:

@csrf_exempt
def heart_beat(request):
    if request.method != 'GET':
        return HttpResponseNotAllowed(['GET'])
    username = request.REQUEST.get('username', None)
    if username is None:
        return HttpResponseBadRequest('username required')

    return HttpResponse('<b>%s</b>' % username)

One thing to point out is since we want to support POST, we use @csrf_exempt to work around Django’s check.

File Manipulation

CreateFile controller

The controller accepts a file stream as data in the request, store that file somewhere on the server, and return to client an id which can be used to retrieve this file.

First, we need to read the upload file stream from the request object

fs = request.FILES.get('file', None)
if fs is None:
    return HttpResponseBadRequest('file is required')

Then, we create a unique id for this file, and use that id to determine where we’ll save the file on the server’s file system

uid = str(uuid.uuid1()).replace('-', '')
savepath = os.path.join(MEDIA_ROOT, 'practise', uid)

Note that MEDIA_ROOT is imported by from web_dev_tutorial.settings import MEDIA_ROOT at the beginning of the practise.py. And in settings.py you can set the variable with something like

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(BASE_DIR, 'upload')

Finally, we save the file, and responses to client with the id

data = fs.read()
out_fs = open(savepath, 'wb')
out_fs.write(data)
out_fs.close()

return HttpResponse(json.dumps({'id': uid}))

GetFile controller

This controller supports retrieval of files. It expects an id as parameter in the request, use that id to locate the file, and return the binary file stream of that file.

First we locate the file with the given id. Note that this controller should only support GET

if request.method != 'GET':
    return HttpResponseNotAllowed(['GET'])
savepath = os.path.join(MEDIA_ROOT, 'practise', file_id)
if not os.path.isfile(savepath):
    return HttpResponseNotFound('Invalid id')

Then, we just create a http response that encapsulates the binary stream of the target file

read_fs = open(savepath, 'rb')
response = HttpResponse(read_fs)
response['Content-Disposition'] = 'attachment; filename=' + \
	os.path.split(savepath)[1]
return response

Putting everything together

@csrf_exempt
def create_file(request):
    fs = request.FILES.get('file', None)
    if fs is None:
        return HttpResponseBadRequest('file is required')

    uid = str(uuid.uuid1()).replace('-', '')
    savepath = os.path.join(MEDIA_ROOT, 'practise', uid)
    data = fs.read()

    out_fs = open(savepath, 'wb')
    out_fs.write(data)
    out_fs.close()

    return HttpResponse(json.dumps({'id': uid}))


@csrf_exempt
def get_file(request, file_id):
    if request.method != 'GET':
        return HttpResponseNotAllowed(['GET'])

    savepath = os.path.join(MEDIA_ROOT, 'practise', file_id)
    if not os.path.isfile(savepath):
        return HttpResponseNotFound('Invalid id')

    read_fs = open(savepath, 'rb')

    response = HttpResponse(read_fs)
    response['Content-Disposition'] = 'attachment; filename=' \
    	+ os.path.split(savepath)[1]

    return response