1

I have a django admin Page where user is uploading a file, the data is read in-memory, without actually storing the file.

Based on the content, a new file is generated on the disk.All this happens in clean method before the save_model is called out.Below is the method which generates the output file

def clean(self):
    obj = Parser()
    cleaned_data = super(MyMethodAdminForm, self).clean()
    input_data = self.request.FILES['file_name'].read().split('\n')
    base_file = settings.MEDIA_ROOT + "/uploads/" + cleaned_data.get('file_name').name

    # This is the output file, which needs to be downloaded
    output_filename = base_file.replace('.csv', '_output.csv')
    output_list = []

    # Read the file and prepare the output data
    # on the basis of the input data
    for line in input_data:
        data = line.split(",")
        if len(data) > 1:
            dt = obj.get_data()
            current_list = [data[0], data[1]]
        else:
            dt = obj.get_data()
            current_list = [data[0]]
        current_list.append(str(dt))
        output_list.append(current_list)

    # Prepare the file on the basis of the output data
    with open(output_filename, 'a') as outcsv:
        # configure writer to write standard csv file
        writer = csv.writer(outcsv, delimiter=',', quotechar=' ', quoting=csv.QUOTE_MINIMAL, lineterminator='\n')
        for item in output_list:
            if len(item) > 2:
                # Write item to outcsv
                writer.writerow([item[0], item[1], item[2]])
            else:
                writer.writerow([item[0], item[1]])
    return cleaned_data

Now, my problem is that i have to allow for this file download, but since, the upload domain is handled through a load balancer, I cant really provide the link (would not be a preferred way too, honestly).Is there any way I can force a prompt for file download?

I got some hints from below two question but then didnt understood wherein do i need to put these change header thing

EDIT

after a little more debugging, i tried updating response_change as suggested in the thread Redirect on admin Save

    class MyMethodAdmin(admin.ModelAdmin):
        form = MyMethodAdminForm

        def response_change(self, request, obj):
            import ipdb;
            ipdb.set_trace()
            # response = HttpResponse(content_type='text/csv')
            # response['Content-Disposition'] = 'attachment; filename="%s"' % form.cleaned_data['output_file_path'] (somehow access the file-path, its incorrect ryt now, i know

            super(MyMethodAdmin, self).response_change(request, obj)

but even pdb is not being called....so no help yet!! :(

complete class :

class MyMethodAdminForm(forms.ModelForm):
    class Meta(object):
        model = MyMethod
        fields = ["file_name"]

    def clean(self):
        obj = Parser()
        cleaned_data = super(MyMethodAdminForm, self).clean()
        input_data = self.request.FILES['file_name'].read().split('\n')
        base_file = settings.MEDIA_ROOT + "/uploads/" + cleaned_data.get('file_name').name
        output_filename = base_file.replace('.csv', '_output.csv')
        output_list = []

        # Read the file and prepare the output data
        # on the basis of the input data
        for line in input_data:
            data = line.split(",")
            if len(data) > 1:
                dt = obj.get_data()
                current_list = [data[0], data[1]]
            else:
                dt = obj.get_data()
                current_list = [data[0]]
            current_list.append(str(dt))
            output_list.append(current_list)

        # Prepare the file on the basis of the output data
        with open(output_filename, 'a') as outcsv:
            # configure writer to write standard csv file
            writer = csv.writer(outcsv, delimiter=',', quotechar=' ', quoting=csv.QUOTE_MINIMAL, lineterminator='\n')
            for item in output_list:
                if len(item) > 2:
                    # Write item to outcsv
                    writer.writerow([item[0], item[1], item[2]])
                else:
                    writer.writerow([item[0], item[1]])
        return cleaned_data
Community
  • 1
  • 1
NoobEditor
  • 15,563
  • 19
  • 81
  • 112

1 Answers1

1

Wherever you’re ready to send your response to the user:

response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
writer = csv.writer(response)
# now write to writer however you want to output your CSV

There are multiple methods that you might have to override depending on where you are calling your view from. The reason for this is that django supports different types of admin actions including change, add, delete which you can read about here. I am not sure which one you are using, so you may have to try both. As a first step, I would try overriding both the response_change and response_add methods:

class MyMethodAdmin(admin.ModelAdmin):
    form = MyMethodAdminForm

    def return_csv(self):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="%s"' % filename
        writer = csv.writer(response)
        writer.writerow(['Django','Admin'])
        return response

    def response_change(self, request, obj):
        return self.return_csv()

    def response_add(self, request, obj):
        return self.return_csv()
2ps
  • 15,099
  • 2
  • 27
  • 47