I am trying to make a METAR decoder as shown:
I am using fetch
in Vanilla js and I plan to send the entered code to a Django view. From the Django view, the decoded data will be taken and displayed in the template.
views.py
def ToolsPageView(request): if request.method == "POST": jsonData = json.loads(request.body) metarCode = jsonData.get('Metar') return JsonResponse("Success", safe=False) return render(request, 'app/tools.html')
urls.py
... path("tools", views.ToolsPageView, name="tools")
tools.html
<div class="metar-code-decode"> <form method="POST" action="{% url 'tools' %}" id="metar-form"> {% csrf_token %} <input type="text" placeholder="Enter METAR: " id="metar-value"> <br> <input type="submit" id="metar-button"> </form> </div>
tool.js
function getDecodedMetar() { let formButton = document.querySelector("#metar-button"); formButton.onclick = function (e) { let metarCode = document.querySelector("#metar-value").value; sendMetar(metarCode); //e.preventDefault(); //getMetar(metarCode); }; } function sendMetar(metarCode) { fetch('/tools', { method: "POST", headers: { "X-CSRFToken": getCookie("csrftoken"), }, body: JSON.stringify({ Metar: metarCode, }), }); }
I have used the same code for POST
using fetch
where I had to let user update his/her profile. And that worked. But, this does not work and the error keeps on changing from time to time after restarting the server. At the first try, there was no error produced and the server also showed a POST
request being made. And the latest error which I am getting is “In order to allow non-dict objects to be serialized set the safe parameter to False.” I get the same thing again and again even after setting safe=False
within the JsonResponse()
. Worth to note, request
when converted to request.json()
gives an error.
Am I using fetch
wrongly? If yes, what is the correct way?
Advertisement
Answer
I’m not sure you have the flow right. The idea is that the button, when clicked, will call a function (fetch) that will send data to the view, which will decode it and send it back to the JavaScript, so that it could be displayed without reloading the entire page.
I think this might help:
let formButton = document.querySelector("#metar-button"); // When the button is clicked, formButton.onclick = function(e) { // do NOT send the form the usual way e.preventDefault(); let metarCode = document.querySelector("#metar-value").value; // Run the function that will send the code to the ToolsPageView sendMetar(metarCode); } async function sendMetar(metarCode) { const response = await fetch('/tools', { method: "POST", headers: { "X-CSRFToken": getCookie("csrftoken"), }, body: JSON.stringify({ 'Metar': metarCode, }), }) .then(response => response.json()) .then(data => { console.log(data); // extract the decoded value from the data sent back from the view // display it by targeting the element in your html that you want // to display it }); }
And in your view,
def ToolsPageView(request): if request.method == "POST": jsonData = json.loads(request.body) metarCode = jsonData.get('Metar') # Remove the original JsonResponse # return JsonResponse("Success", safe=False) # and INSTEAD, # Send the code back to the JavaScript # I don't THINK you need safe=False here? return JsonResponse({'MetarCode': metarCode}) return render(request, 'app/tools.html')