0

I'm working on a solution which translates CSV/TSV files from one language to the other. I've built a Django application that accepts the file and the target/source language(s) using a form.

Once the user provides the data, the file is processed (which takes some time). Now I know we can return a fileresponse to the user. However, as I mentioned it takes time for the file to be translated and a new file is created which would contain the translated contents.

And in the meantime, I don't want to make the user waiting on the form...waiting for the response.

The models.py file is:

from django.db import models
from django.core.validators import FileExtensionValidator

file_type_choices = [
    ('CSV', 'Comma-Separated Values'),
    ('TSV', 'Tab-Separated Values')
]
valid_extensions = ['tsv', 'csv']
# Create your models here.
class FileModel(models.Model):
    file = models.FileField(upload_to="files", \
                            validators=[FileExtensionValidator(allowed_extensions=valid_extensions)])
    file_type = models.CharField("Choose your file type", choices=file_type_choices,max_length=3)
    source_language = models.CharField("Choose the language in which file is", max_length=30)
    target_language = models.CharField("Choose the language to which you want to translate the file", max_length=30)

the forms.py file:

from django import forms
from django.core.validators import FileExtensionValidator

file_type_choices = [
    ('CSV', 'Comma-Separated Values'),
    ('TSV', 'Tab-Separated Values')
]

valid_extensions = ['tsv', 'csv']

class FileUploadForm(forms.Form):
    file = forms.FileField(allow_empty_file=False, \
                           validators=[FileExtensionValidator(allowed_extensions=valid_extensions)])
    file_type = forms.ChoiceField(choices=file_type_choices, widget=forms.Select(attrs={"class": "form-control"}))
    source_language = forms.CharField(max_length=30,\
                                      widget=forms.TextInput(attrs={"class":"form-control", "placeholder": "English"}))
    target_language = forms.CharField(max_length=30, \
                                      widget=forms.TextInput(attrs={"class":"form-control"}))

the views.py contains the following code:

from django.shortcuts import render
from django.http import HttpResponseRedirect, request
from .forms import FileUploadForm
from .models import FileModel
from django.views import View
from csv_trans import translate

class CreateProfileView(View):
    def get(self, request):
        form = FileUploadForm()
        return render(request, "translate/index.html", {"form": form})
    
    def post(self, request):
        submitted_form = FileUploadForm(request.POST, request.FILES)

        if submitted_form.is_valid():
            file_instance = FileModel( file = request.FILES['file'], \
                             file_type = request.POST['file_type'], \
                             source_language = request.POST['source_language'], \
                             target_language = request.POST['target_language'])
            file_instance.save()
            
            separator = "," if file_instance.file_type == "CSV" else "\t"
            """ if file_instance.file_type == 'CSV':
                separator = ','
            else:
                separator = '\t' 
            """
            print(separator)
            translate(str(file_instance.file), file_instance.source_language, \
                      file_instance.target_language, separator)
            
            return HttpResponseRedirect("/thanks")
        
        return render(request, "translate/index.html", {"form":submitted_form})

Now in the views.py file, I'm currently using the HTTPResponse to redirect to another URL. But here I want to send a file (translated file) to the user, after the file that the user entered in the form has been translated.

The csv-trans module contains the necessary code for translating the code.

The template index.html contains the following HTML code alongwith DTL:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Translate data to English</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
    </head>

    <body>
        <div class="col-md-6 offset-md-3 mt-5">
          <div class="form-group">
             <form class = "form-control" accept-charset="UTF-8" method="POST" enctype="multipart/form-data" target="_blank">
                {% csrf_token %} 
               {{form.as_p}}
               <button type="submit" class="btn btn-primary">Translate</button>
             </form>
            </div>
         </div>
    </body>
</html>

1 Answers1

0

Let me show you two ways to serve files in Django.

First: Serving files on the fly (when they are not stored in your filestorage) but are created during runtime.

from django.http import FileResponse
    def get(self, request, *args, **kwargs):
        buffer = io.BytesIO()
        your_file = create_file_logic()
        your_file.save(buffer)


        # FileResponse sets the Content-Disposition header so that browsers
        # present the option to save the file.
        buffer.seek(0)
        return FileResponse(buffer, as_attachment=True, filename=f"my_filename.xyz")

Second: Serving files from storage

from django.http import FileResponse
    def get(self, request, *args, **kwargs):

        return FileResponse(open(path_to_file, 'rb'), as_attachment=True, filename="my_filename")

Hope this helps

Tarquinius
  • 1,468
  • 1
  • 3
  • 18