skip to Main Content

I have a dropdown list that I got from an uploaded CSV file from Django that I want to pass back to a different Django view with javascript when selected. I keep getting a 404 error (index.js:9 POST http://127.0.0.1:8000/gui_app/%7B%%20url%20%22get_selection%22%20%%7D 404 (Not Found) (anonymous) @ index.js:9 ) when I click on the select button after I choose a value from the dropdown. From what I understand reading the error message, the issue seems to be coming from javascript not being able to render the url the correct way. What’s the correct way to pass the url in javascript so that javascript recognizes it and passes the data to the view? Here’s my code below

index.js


let signalSelectButton = document.getElementById("signalSelectButton")
const url = loacation.href('/get_selection/')

signalSelectButton.addEventListener("click", function() {
  console.log("clicked")
  const selectedValue = document.getElementById("signalSelect").value
  console.log(selectedValue)
  
  fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRFToken': '{{ csrf_token }}'
    },
    body: JSON.stringify({selected_value: selectedValue})
    })
    .then(response => {
      if (!response.ok) {
        throw new Error('Network response was not ok')
      }
      return response.json()
    })
    .then(data => {
      console.log(data)
      document.getElementById('response-message').innerText = data.message
  })
    .catch(error => {console.error('Error:', error)})
})

views.py

from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from .forms import SigFileForm
from django.contrib import messages
from django.views.decorators.csrf import csrf_exempt
import os
import pandas as pd

# Create your views here.
def index(request):
    return HttpResponse("Hello, world!")
        
def model_upload(request):
    # return render(request, 'model_upload.html')
    if request.method == 'POST':
        form = SigFileForm(request.POST, request.FILES)
        if form.is_valid():
            sigfile = request.FILES['file']
            sigfile_name = sigfile.name
            sigfile_size = sigfile.size
            instance = form.save()
            sigfile_url = instance.file.url
            choices = populate_dropdown(sigfile_url)
            messages.success(request, 'File uploaded successfully!')
            return render(request, 'model_upload.html', {'form': form, 'choices': choices})
        else:
            return render(request, 'model_upload.html', {'form': form})
    else:
        form = SigFileForm()
        return render(request, 'model_upload.html', {'form': form})
        
def populate_dropdown(file_url):
    file_path = os.path.join(settings.MEDIA_ROOT, file_url.lstrip('/media/'))
    if os.path.exists(file_path):
        df = pd.read_csv(file_path, sep = ',', index_col = 'Time,ms')
        choices =  df.columns.values.tolist()
        return choices
    else:
        print(f'File does not exist: {file_path}')
        return []
        
@csrf_exempt
def get_selection(request):
    if request.method == 'POST':
        selected_value = request.POST.get('selected_value')
        return JsonResponse({'message': f'You selected: {selected_value}'})
    else:
        return JsonResponse({'message': ''})

urls.py

from django.urls import path

from . import views

urlpatterns = [
    path("", views.index, name = "index"),
    path("simple_upload", views.simple_upload, name = "simple_upload"),
    path("model_upload", views.model_upload, name = "model_upload"),
    path("get_selection", views.get_selection, name = "get_selection"),
]

2

Answers


  1. To startspelt location wrong at the start const url = loacation.href('/get_selection/') but I expect that may be a typo you’ve noticed.

    That aside as you just want to make the request to an endpoint controlled by Django use the built-in template tag {% url "get_selection" %} to determine the URL to set, as reference by the built-in templatetag docs here https://docs.djangoproject.com/en/5.1/ref/templates/builtins/#url

    If you are only using the "url" constant in that one place then I’d suggest not using it at all and changing your fetch to be this
    fetch("{% url "get_selection" %}", { ...

    Login or Signup to reply.
  2. Since data is JSON and not form data it requires a different processing. While using @csrf_exempt decorator it is not necessary to include 'X-CSRFToken' header. Also, its possible to use data attributes together with Django’s reverse resolution of URLs. Here is a minimal example:

    <body>
    <label for="cars">Choose a car:</label>
    
    <select name="cars" id="signalSelectBox" data-url="{% url 'get_selection' %}">
        <option value="volvo">Volvo</option>
        <option value="saab">Saab</option>
        <option value="mercedes">Mercedes</option>
        <option value="audi">Audi</option>
    </select>
    <button id="signalSelectButton">select</button>
    </body>
    

    script.js

    const signalSelectButton = document.getElementById("signalSelectButton");
    const signalSelectBox = document.getElementById("signalSelectBox");
    const url = signalSelectBox.dataset.url;
    
    signalSelectButton.addEventListener("click", sendRequest);
    
    async function sendRequest() {
        let selectedValue = signalSelectBox.value
        try {
            const response = await fetch(url, {
                method: "POST",
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({selected_value: selectedValue})
            })
    
            const data = await response.json();
    
            console.log(data.message);
    
        } catch (error) {
            console.log(error)
        }
    
    }
    

    views.py

    import json
    
    @csrf_exempt
    def get_selection(request):
        if request.method == 'POST':
            data = json.loads(request.body)
            selected_value = data['selected_value']
            return JsonResponse({'message': f'You selected: {selected_value}'})
        else:
            return JsonResponse({'message': ''})
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search