I am making a website that takes user text, modifies it and returns a response using Ajax. I am using Django on the backend and vanilla JS on the frontend. The user chooses source_language
and target_language
, enters some text in input_text and the browser outputs a translation in the output_text textarea. However whenever I try I keep getting either a None
as output_text(as the output from my translation API) or a No Null
error for input text whenever it tries to save to the database, so it seems the input text is not being detected by my django view. The same goes for the source language and target language. When I comment out the code to save translation to the database I get None
as ouput text. However when I check the payload (in developer tools) being sent I see the input text and the selected languages. I use the <form>
tag in my HTML with AJAX so as to prevent page reloads when the user recieves a response. When I remove all JS it works as expected but of course the presenation is a black screen and requires a page reload. Here is my code:
JS:
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
document.addEventListener('DOMContentLoaded', () => {
//const myForm = document.getElementById('translate-form');
const myForm = document.querySelector('#translate-form');
myForm.addEventListener('submit', (e) => {
e.preventDefault();
/* Convert form data to JSON */
let formData = new FormData(e.target);
formData = formDataToJSON(formData);
/* Create a new Request object */
let request = new Request('/translator/', {
method: 'POST',
body: formData,
headers: { 'content-type': 'application/json',
'X-CSRFToken': csrfToken
}
});
/* Send the request and wait for response */
fetch(request)
.then(response => {
if (!response.ok) throw new Error('Failed to send request.');
return response.json();
}).then(data => {
/* Do something with data from response */
console.log(data);
//let outputTextArea = document.getElementById('translate-form');
outputTextArea.value = !data.output_text ? `Translation error: ${data.error}` : data.output_text;
}).catch(console.error);
});
});
/* Converts FormData to JSON */
function formDataToJSON(formData) {
let obj = {};
for (let key of formData.keys()) obj[key] = formData.get(key);
return JSON.stringify(obj);
}
Here is Django view:
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render
from django.http import HttpResponse
from .models import TranslationRequest
@csrf_protect
def translateText(request):
if request.method == 'POST':
source_language = request.POST.get('source_language')
input_text = request.POST.get('input_text')
target_language = request.POST.get('target_language')
try:
# Call the API for translation logic
output_text = translation_via_API
# Save the translation to database
translation_object = TranslationRequest.objects.create(
source_language = source_language,
target_language = target_language,
input_text = input_text,
output_text = output_text
)
return JsonResponse({'output_text': output_text})
except Exception as e:
# Handle API and model save errors here
error_message = f"An error occurred: {e}"
return JsonResponse({'error': error_message}, status=500)
return render(request, 'translator/index.html', {response})
return render(request, 'translator/index.html')
Here is the relevant HTML:
<form id="translate-form" action="{% url 'translateText' %}" method="post">
{% csrf_token %}
<label for="input-lang-select"></label>
<select class="input-lang-select" name="source_language">
<option value="zh">Chinese</option>
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="de">German</option>
<option value="jp">Japanese</option>
<option value="ko">Korean</option>
<option value="ru">Russian</option>
<option value="pt">Portugese</option>
<!-- add more language options as needed -->
</select>
</div>
<!--<p class="box-title">Detected language: <span id="detected-language">Detecting...</span></p>-->
<textarea id="input-text-area" name="input_text"
autofocus
minlength="1"
maxlength="10000"
placeholder="Enter text here"></textarea>
<!--change min and maxlength-->
<div class="submit-btn-container">
<button type="submit" id="submit">Translate</button>
</div>
<div class="word-count-div">
<span class="word-count"><span class="string-count">0</span>/10000</span>
<!--change max wordcount-->
</div>
</div>
<div class="output-box">
<div class="output-lang-select-div">
<label for="output-lang-select">></label>
<select class="output-lang-select" name="target_language">
<option value="en">English</option>
<option value="zh">Chinese</option>
<option value="es">Spanish</option>
<option value="de">German</option>
<option value="jp">Japanese</option>
<option value="ko">Korean</option>
<option value="ru">Russian</option>
<option value="pt">Portugese</option>
<!-- add more language options as needed -->
</select>
</form>
Here's my mysite\urls.py:
```
from django.contrib import admin
from django.urls import include, path
from translator import views
urlpatterns = [
path('translator/', include('translator.urls')),
path('admin/', admin.site.urls),
]
```
And my translator\urls.py:
```
from django.urls import path
from . import views
urlpatterns = [
path("", views.translateText, name = "translateText"),
]
```
I read Django documentation back and forth and tried everything I understood but it made no difference. And as I said on checking the payload I saw that each field is being sent to the backend with the relevant data.