Как работать с надежными выпадающими списками в Django - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь создать надежный раскрывающийся список для Django, но поскольку мои знания JavaScript / ajax невелики, я достиг дна. Примечание: я прочитал предыдущие вопросы по этому поводу, но ни один из них не решил мою проблему полностью.

Описание проблемы:

Из-за моей базы данных size, я получаю частичные данные с сервера всякий раз, когда запрашивается представление. Это усложняет мою работу по использованию форм, поскольку я использую имя пользователя для фильтрации своего сервера. Вот упрощенная версия моего кода.

urls.py


urlpatterns = [
    url(r'^SpecificVessel', views.SpecificVessel, name="goSpecificVessel"),
]

views.py

@login_required
def SpecificVessel(request):

  #Get the username to filter the tables from SQL Server:
  username = None
  if request.user.is_authenticated:
      username = request.user.username

  #Get the shipnames. 
  cursor.execute("select distinct SHIPNAME from Table where [GROUP]=" + "'" + username + "'")
  row = cursor.fetchall() 
  df_listofships = pd.DataFrame(data=row, columns=['SHIPNAME'])
  shipnames = list(df_listofships['SHIPNAME'].tolist())  # LIST FOR SHIP SELECTION

  #Get All the data from database.
  cursor.execute("select * from Table2 where [GROUP]=" + "'" + username + "'")
  row = cursor.fetchall()
  df = pd.DataFrame(data=row)
  colnames = list(dftrans.columns.values.tolist()) #LIST FOR YEAR DROPDOWN SELECTION

  #getting the dropdown selections:
  Dropdown_shipname = request.POST.get('Dropdown_shipname')
  Dropdown = request.POST.getlist('Dropdown')
  
  
  return render(request, 'SpecificVessel.html', 
               {'colnames': colnames, 'Dropdown': Dropdown, 'shipnames': shipnames, 'Dropdown_shipname': Dropdown_shipname,})

SpecificVessel. html

<form method="post">
   {% csrf_token %}
   <div class="form-group col-md-4">
        <label for="Dropdown_shipname"><b>Select Vessel</b></label>
               <select name="Dropdown_shipname" id="Dropdown_shipname" data-style="btn-default" class="selectpicker form-control" >
                   {% for i in shipnames %}
                       <option value="{{ i }}" {% if Dropdown_shipname == i %}  selected {% endif %}>{{ i }} </option>
                   {% endfor %}
                </select>
   </div>



   <div class="form-group col-md-4">
       <label for="Dropdown"><b> Select Month </b></label>
             <select name="Dropdown" id="Dropdown" data-style="btn-default" class="selectpicker form-control" multiple>
                  {% for i in colnames %}
                       <option value="{{ i }}" {% if Dropdown == i %}  selected {% endif %} >{{ i }} </option>
                  {% endfor %}
              </select>
   </div>
            

   <div class="form-group col-md-1 margin_top_25">
        <input type="submit" value="Submit" />
   </div>
            
</form>

В чем проблема?

Решение, которое я нашел в приведенном выше коде, предоставляет мне независимые выпадающие списки. То есть всякий раз, когда есть несоответствие, это выдает мне ошибку. Я пытался подойти к этому по-другому, однако после долгих исследований в Интернете я обнаружил, что javascript или ajax могут быть способом go по этому поводу. У меня такой вопрос: Есть ли способ получить то, что пользователь выбрал в Dropdown_shipname, прежде чем он отправит результаты? Если да, то как бы вы решили эту проблему?

Надеюсь, я был достаточно ясен. Пожалуйста, дайте мне знать, если я должен объяснить проблему лучше.

1 Ответ

2 голосов
/ 05 августа 2020

Мне кажется, мне нужно многое обсудить, прежде чем отвечать на ваш главный вопрос.

  1. Бит if request.user.is_authenticated не нужен; вы уже украшаете представление @login_required, поэтому пользователь не может быть аутентифицирован.
  2. Откуда взялось cursor? Не похоже, что вы используете базу данных Django (ORM или даже необработанные курсоры), а что-то еще? Это почему?
    • Наличие глобального cursor может привести к сбоям в работе производственной линии, когда он распределяется между запросами в многопоточной ситуации. (Используя функциональные возможности базы данных Django, соединения с базой данных правильно сбрасываются между запросами, и каждый поток получает собственное соединение.)
  3. Ваши запросы SQL уязвимы для SQL инъекционные атаки, поскольку вы просто объединяете строки вместе. Вместо этого вам нужно использовать заполнители (параметризованные запросы). Как это делается, зависит от базы данных и драйвера базы данных, который вы используете.
  4. Вам определенно не нужны Pandas и Pandas фрейм данных для извлечения данных из результата вашей базы данных! (Моя любимая мозоль: бесполезное использование Pandas.)
    • Первое извлечение будет shipnames = [row[0] for row in cursor].
    • Второе извлечение будет colnames = [d[0] for d in cursor.description] (или подобное; зависит от вашей базы данных ). (Однако вы действительно не хотите получать несколько строк только для того, чтобы получить имена столбцов; подойдет одна строка, например LIMIT 1 в стандартном SQL.)
  5. Вы должны использовать Django формы для управления формами. Таким образом, вам не нужно вручную управлять рендерингом <select> s, <option> s и selected s.
    • Это представление, скорее всего, станет подклассом FormView.
    • Вы говорите: «Это усложняет мою работу по использованию форм, поскольку я использую имя пользователя для фильтрации моего сервера», но это не проблема. Вы можете передать свой Django request, или просто User, или username в настраиваемый класс формы и заставить его изменять или даже динамически добавлять поля в форму на его основе.

Тем не менее, самым минимальным решением здесь является небольшой бит JavaScript, чтобы обновить sh страницу с добавленным аргументом строки запроса для первого выбора. То есть, когда пользователь изменяет поле имени корабля, вы должны обновить sh страницу, например, ?shipname=selection-here, и заняться поиском правильных вариантов для другого поля в вашем коде просмотра.

Самый минимальный способ, который я могу придумать, - это

<script>
document.getElementById("Dropdown_shipname").addEventListener("change", (event) => {
  location.href = `?shipname=${event.target.value}`;
}, false);
</script>

Кроме того, вы можете использовать запрос AJAX для выборочного обновления sh только части страницы, а кроме того, возможно, рефакторинг формы в: скажем, компонент React. js или Vue. js, который имеет дело с формой.

Но в любом случае, нет, вы не сможете динамически изменять другое поле без JavaScript.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...