Skip to content
Advertisement

How to correctly use Fetch in JavaScript and Django?

I am trying to make a METAR decoder as shown:here

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')
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement