How to return multiple files in HttpResponse Django

I have been wracking my brains in this problem. Is there a way in django to serve multiple files from a single HttpResponse?

I have a scenario where i am looping through a list of json and want to return all those as file form my admin view.

class CompanyAdmin(admin.ModelAdmin):
    form = CompanyAdminForm
    actions = ['export_company_setup']

    def export_company_setup(self, request, queryset):
        update_count = 0
        error_count = 0
        company_json_list = []
        response_file_list = []
        for pb in queryset.all():
            try:
                # get_company_json_data takes id and returns json for the company.
                company_json_list.append(get_company_json_data(pb.pk))
                update_count += 1
            except:
                error_count += 1

        # TODO: Get multiple json files from here.
        for company in company_json_list:
            response = HttpResponse(json.dumps(company), content_type="application/json")
            response['Content-Disposition'] = 'attachment; filename=%s.json' % company['name']
            return response
        #self.message_user(request,("%s company setup extracted and %s company setup extraction failed" % (update_count, error_count)))
        #return response

Now this will only let me return/download one json file as return would break the loop. Is there a simpler way to just append all this in a single response object and return that outside loop and download all json in the list in multiple files?

I looked through a way to wrap all these files into a zip file, but i failed to do so as all the examples that i could find had files with path and name which i don't really have in this case.

UPDATE:

I tried to integrate zartch's solution to get a zip file using following:

    import StringIO, zipfile
    outfile = StringIO.StringIO()
    with zipfile.ZipFile(outfile, 'w') as zf:
        for company in company_json_list:
            zf.writestr("{}.json".format(company['name']), json.dumps(company))
        response = HttpResponse(outfile.getvalue(), content_type="application/octet-stream")
        response['Content-Disposition'] = 'attachment; filename=%s.zip' % 'company_list'
        return response

Since i never had the files to begin with, i thought about just using json dump that i had and adding individual filename. This just creates an empty zipfile. Which i think is expected as i am sure zf.writestr("{}.json".format(company['name']), json.dumps(company)) is not the way to do it. I would appreciate if anyone can help me with this.


Solution 1:

Maybe if you try to pack all files in one zip you can archive this in Admin

Something like:

    def zipFiles(files):
        outfile = StringIO()  # io.BytesIO() for python 3
        with zipfile.ZipFile(outfile, 'w') as zf:
            for n, f in enumerate(files):
                zf.writestr("{}.csv".format(n), f.getvalue())
        return outfile.getvalue()

    zipped_file = zip_files(myfiles)
    response = HttpResponse(zipped_file, content_type='application/octet-stream')
    response['Content-Disposition'] = 'attachment; filename=my_file.zip'