Отправка значения JavaScript в метод на views.py (Django)

Я использую django (4.0.4) для разработки "простого" интерфейса с тремя выпадающими списками, в которых данные последних двух зависят от выбранного значения первого.

Это передняя часть:

enter image description here

Это структура проекта dir:

├── db.sqlite3
├── manage.py
├── example_web
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── web
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    ├── models.py
    ├── static
    │   ├── css
    │   │   └── style.css
    │   └── js
    │       └── app.js
    ├── templates
    │   ├── index.html
    ├── tests.py
    └── views.py

Это urls.py

from django.contrib import admin
from django.urls import path
from web.views import homePageView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', homePageView),
]

views.py

from django.shortcuts import render
from django.template import loader
from django.http import HttpResponse
from jf.clients import RPClient




def homePageView(request):

    a = _get_coaches()
    b = _get_devices()
 
    value_js = request.GET.get('id')
    print(value_js)

    context = {
        'coaches': a,
        'devices': b,

    }

    return render(request, 'index.html', context)
 

def _get_coaches():
    client = RPClient('dev', proxy_ip='10.10.1.15')
    a = client.get_current_value('status/coach')

    return [i['id'] for i in a['items']]


def _get_devices(request):
    client = RPClient('dev', proxy_ip='10.10.1.15')
    a = client.get_current_value('status/cable/X')
    
    # !!!!!!!!!!

    # HERE is where in the X place I want to store the value_js variable 

    return [i['id'] for i in a['items']]

Это js, css и html

function value_id() {
  coach_id = document.getElementById("coaches").value;
  window.alert('ID Selected: ' + coach_id);
  $.ajax({
    type: "POST",
    url: '',
    data: {
      'id': coach_id
    }
  })
}
body {
  background: #fafafa;
  font-size: 1.25em;
  font-family: 'Raleway', sans-serif;
}

h1 {
  text-align: center;
  font-size: 48px;
  margin-top: 50;
  margin-bottom: 50;

}

section {
  width: 100%;
  min-height: 100vh;
  display:inline-block;
  justify-content: left;
  align-items: flex-start;
  background: #fafafa;
  padding-left: 180;
  margin-top: 250;
  width: 225px;

}

div {
  position: fixed;
}

select option:hover {
    margin: 40px;
    background: #4780D5;
    color: #fff;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
}

.selectColor {
  position: relative;
  padding: 10px;
  background: #fafafa;
  border: none;
  outline: none;
  width: 200px;
  border-radius: 4px;
  box-shadow: 0 15px 25px rgba(0, 0, 0, 0.1);
}

.header {
  position: fixed;
    width: 100%;
    background-color: #4780D5;
    top: 0;
    left: 0;
    color:#fafafa;
    opacity: 0.8;
}
    {% load static %}
    
    <title>Website</title>
    
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
    <script src="{% static 'js/app.js' %}"></script>
    
    <html>   
        <body>
            <div class="header">
                <h1>Example</h1>
            </div>
            
            <div>
            <section>
              <select id='coaches' class="selectColor" onchange="value_id()">
                <option  value="">Select Coach</option>
                {% for coach in coaches%}
                <option id='test' value="{{ coach }}">Coach {{coach }}</option>
                {% endfor %}
              </select>            
            </section>
    
            <section>
              <select id='devices'  class="selectColor" onchange="value_device()">
                <option value="">Select Device</option>
                {% for device in devices%}
                <option style="text-transform:uppercase;" value="{{ device }}">{{ device }}</option>
                {% endfor %}
              </select>
            </section>
    
    
          </div>
          </body>
    </html>
    
    {% block page_content %}{% endblock %}

Первый выпадающий список автозаполняется путем выполнения get запроса к конечной точке, например /status/coach и я получаю ID.

Таким образом, первый выпадающий список будет выглядеть примерно так:

  • Тренер 1
  • Тренер 2
  • Тренер 3

Мне нужно, чтобы второй выпадающий элемент также делал get запрос к той же конечной точке, добавляя id, который он берет в конце, т.е. если я выбираю в выпадающем элементе 'Coach 2', то конечная точка будет /status/coach/2

Но я не знаю, как отправить значение id, которое я храню в coach_id, в js файл и в метод в файле views.

Согласно примерам, которые я прочитал здесь, они предложили две вещи: отправить эту переменную с помощью ajax (я никогда не использовал js до этого момента, так что, возможно, есть вещи, которые являются неправильными), но когда я пробую это, я всегда получаю None в качестве значения переменной 'coach_id' и появляется только при перезагрузке страницы на django debug, не появляется, когда я выбираю элемент из списка, только window. alert работает...что я делаю не так?

Другая альтернатива, которую я видел, заключается в том, чтобы поместить структуру тегов section и select внутрь формы, например this, но мне не нужна кнопка post с формой

Итак... как я могу отправить значение ID выбранного автомобиля в файл views в методе get_devices()?

Спасибо!

Вы можете передать this в качестве аргумента в вызов onchange и в javascript вы можете получить это как element.

<select id='coaches' class="selectColor" onchange="value_id()">

В javascript

function value_id(thisValueElement) {
 const value = thisValueElement.value
 
 const endpoint = "{% url 'your_homepage_view_url' %}
 fetch(endpoint + "?coach_id=" + value)
  .then(res => res.json())
  .then(response => { 
    // Return JsonResponse from server and get the value here.
  })
}

А затем в вашем представлении вы получаете это из GET-запроса.

def homePageView(request):
    coach_id = request.GET.get("coach_id", default_id_here_if_not_omit_this)
    a = _get_coaches()
    b = _get_devices()
 
    value_js = request.GET.get('id')
    print(value_js)

    context = {
        'coaches': a,
        'devices': b,

    }

    return render(request, 'index.html', context)
Вернуться на верх