Arrow
Arrow14 января 2019 г. 11:42

Сохранение данных из выпадающего списка в модель

select, choices

Добрый день!

Возникла проблема с выпадающим списком, а точнее с сохранением из него данных.

Приведу простой пример.

Модель имеет вид (models.py)

from django.db import models

# Create your models here.
class Test(models.Model):
    METRIC = 'metric'
    IMPERIAL = 'imperial'
    ATHER = ''
    UNIT = (
        (METRIC, 'kg'),
        (IMPERIAL, 'lb'),
        (ATHER, 'none')
    )
    name = models.CharField(max_length=25)
    temperature_unit = models.CharField(max_length=8,
                                        choices=UNIT,
                                        default=METRIC)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'tests'

Файл forms.py

from django.forms import ModelForm, TextInput
from .models import Test

class TestForm(ModelForm):
    class Meta:
        model = Test
        fields = ['name', 'unit']
        widgets = {'name': TextInput(attrs={'class': 'input', 'placeholder': 'Name'})}

Файл *.html

<form method="POST">
    {% csrf_token %}
        <div class="field has-addons">
            <div class="control is-expanded">
                {{ form.name }}
            </div>
            <select>
                {% for temp in form.tunit %}
                    <option value=""{{ temp.data.value }}>{{ temp.data.label }}</option>
                {% endfor %}
             </select>
             <div class="control">
                <button type="submit" class="button is-info">
                    Add Unit
                </button>
            </div>
        </div>
</form>

В результате в качестве value выпадающего списка (temp.data.value) оказывается 'metric', 'imperial' и '', а в самом выпадающем списке на странице оказывается (temp.data.label): kg, lb, none. Как и должно быть.

Только при вводе данных в поле формы (name = models.CharField(max_length=25)) и попытке сохранения вылетает ошибка. В результате просмотра request.POST в нем оказывается только значение 'name' без 'unit'.

Файл views.py

import requests
from django.shortcuts import render
from .models import Test
from .forms import TestForm

def index(request):
    url = 'http://api.site.org/data/2.5/?q={}&units={}&id=1111&appid=111111111'

    if request.method == 'POST':
        # Здесь request.POST нет данных unit только name
        # Вылетает ошибка
        form = TestForm(request.POST) 
        form.save()

    tests = Test.objects.all()

    test_data = []

    for test in tests:
        # Преобразование данных из metric в kg итд.
        r = requests.get(url.format(test, test.unit)).json()
        res = [data for (t_type, data) in Test.UNIT if t_type == test.unit]

        test_w = {
            'name': test.name,
            'unit': res[0],
            'temp': r['main']['temp'],
            'description': r['data'][0]['description'],
            'icon': r['data'][0]['icon'],
        }

        test_data.append(test_w)

    context = {'test_data': test_data, 'form': form}

    return render(request, 'module/module.html', context)

Что я делаю не так?
Возможно есть другой способ более правильный:
поместить данные о unit в отдельную таблицу в базе данных и вытягивать от туда или еще как-то?

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

18
Evgenii Legotckoi
  • 14 января 2019 г. 11:46

Добрый день!

Так у вас в модели поде unit объявлено как temperature_unit

Вы имя перепутали

Так нужно

from django.forms import ModelForm, TextInput
from .models import Test

class TestForm(ModelForm):
    class Meta:
        model = Test
        fields = ['name', 'temperature_unit']
        widgets = {'name': TextInput(attrs={'class': 'input', 'placeholder': 'Name'})}

Ну и так далее везде поменяйте unit на temperature_unit

    Arrow
    • 14 января 2019 г. 11:52

    Я уже поправил. Скопировал данные из реального и тестово проектов. Ошибка вышла. Извините. :(

      Arrow
      • 14 января 2019 г. 11:53
      • (ред.)

      Но вопрос остался

        Arrow
        • 14 января 2019 г. 13:59

        Посмотрел документацию, делаю правильно, но не работает.

          Evgenii Legotckoi
          • 14 января 2019 г. 14:54

          я так понимаю, у вас там в шаблоне пропущены id и name поля, поэтому и пропускаются значения, а они там должны быть.

          <select id="id_temperature_unit" name="temperature_unit">
              {% for temp in form.temperature_unit %}
                   <option value=""{{ temp.data.value }}>{{ temp.data.label }}</option>
              {% endfor %}
          </select>
          

          Вообще у Field есть методы для получения этих всех id и name, но я как-то не помню их, нужно в документации покопаться.

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

            Arrow
            • 14 января 2019 г. 14:55

            Все исправил, все пересмотрел еще раз.
            Понять не могу почему я в качестве request.POST при попытке сохранения данных, от формы получаю:

            {'csrfmiddlewaretoken': 'BrD9OchYiCLJJAV3U8MX7NewnCO2uZ2EjmyfOIesySZp6dmcyoA1GRwnwReSch0T',
            'name': 'Unit1'}

            а не:

            {'csrfmiddlewaretoken': 'BrD9OchYiCLJJAV3U8MX7NewnCO2uZ2EjmyfOIesySZp6dmcyoA1GRwnwReSch0T',
            'name': 'Unit1', temperature_unit: 'kg'}

              Evgenii Legotckoi
              • 14 января 2019 г. 15:03
              • (ред.)

              А как выглядит отрендеренная форма? В смысле html можете показать итоговый?
              То есть открываете страницу с формой и через браузер посмотрите html и покажите, что там вышло.
              Вот например у меня в одной из форм так получается.

              <select name="type" id="id_type" class="form-control" title="">
                  <option value="T" selected="">Руководство</option>
                  <option value="N">Новости</option>
                  <option value="S">Сниппет</option>
                  <option value="O">Заметка</option>
              </select>
              
                Arrow
                • 14 января 2019 г. 15:08
                • (ред.)

                После исправления:

                <select id="id_temperature_unit" name="temperature_unit">
                    {% for temp in form.temperature_unit %}
                         <option value=""{{ temp.data.value }}>{{ temp.data.label }}</option>
                    {% endfor %}
                </select>
                

                Получаю:

                {'csrfmiddlewaretoken': ['EvCSJRprJbsn3Rte7AxtnpeXeNO3pIThmqxYJnmVZrG3quUnLQlxWtwOn2eT70Rw'], 'name': ['Lviv'], 'temperature_unit': ['']}

                Только что-бы я не выбрал в списке значение temperature_unit не меняется.

                Форма выглядит так:

                Пытаюсь на сайт притулить индикатор погоды с выбором в каких унитах показывать температеру.

                  Evgenii Legotckoi
                  • 14 января 2019 г. 15:12

                  Нет, вы не поняли, покажите мне отрендеренный html из консоли браузера.

                  Вот отсюда

                    Arrow
                    • 14 января 2019 г. 15:16

                    Все ясно:

                      Evgenii Legotckoi
                      • 14 января 2019 г. 15:18
                      • Ответ был помечен как решение.

                      И кстати да, я увидел вашу ошибку,

                      вот ваш код

                      <select id="id_temperature_unit" name="temperature_unit">
                          {% for temp in form.temperature_unit %}
                               <option value=""{{ temp.data.value }}>{{ temp.data.label }}</option>
                          {% endfor %}
                      </select>
                      

                      а вот как надо

                      <select id="id_temperature_unit" name="temperature_unit">
                          {% for temp in form.temperature_unit %}
                               <option value="{{ temp.data.value }}">{{ temp.data.label }}</option>
                          {% endfor %}
                      </select>
                      

                      Найдёте, где кавычки перепутали?

                        Arrow
                        • 14 января 2019 г. 15:18
                        • (ред.)

                        Нашел ошибку. Было:

                        option value=""{{ temperature.data.value }}>{{ temperature.data.label }}

                        Нужно:

                        option value="{{ temperature.data.value }}">{{ temperature.data.label }}

                          Arrow
                          • 14 января 2019 г. 15:20

                          Оказывается все было правильно кроме кавычки :) Буду чаше заглядывать в Инспектор.

                          Огромное спасибо! :)

                            Evgenii Legotckoi
                            • 14 января 2019 г. 15:22

                            Я с консолью браузера при разработке на django вообще не расстаюсь. Иначе можно голову долго ломать.

                              Arrow
                              • 14 января 2019 г. 15:25

                              Теперь так и буду делать :)

                                Arrow
                                • 14 января 2019 г. 15:53
                                • (ред.)

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

                                models.py

                                from django.db import models
                                
                                class TempUnit(models.Model):
                                    name = models.CharField(max_length=2)
                                    unit = models.CharField(max_length=8)
                                
                                    def __str__(self):
                                        return self.name
                                
                                
                                class City(models.Model):
                                    name = models.CharField(max_length=25)
                                    temperature_unit = models.ForeignKey(TempUnit, on_delete=models.CASCADE)
                                
                                    def __str__(self):
                                        return self.name
                                
                                    class Meta:
                                        verbose_name_plural = 'cities'
                                
                                

                                views.py

                                def index(request):
                                    url = 'http://api.site.org/data/2.5/?q={}&units={}&id=1111&appid=111111111111'
                                
                                    if request.method == 'POST':
                                        form = CityForm(request.POST)
                                        form.save()
                                
                                    cities = City.objects.all()
                                    weather_data = []
                                
                                    for city in cities:
                                        r = requests.get(url.format(city, city.temperature_unit)).json()
                                
                                        city_weather = {
                                            'city': city.name,
                                            'temperature_unit': city.temperature_unit,
                                            'temperature': r['main']['temp'],
                                            'description': r['weather'][0]['description'],
                                            'icon': r['weather'][0]['icon'],
                                        }
                                
                                        weather_data.append(city_weather)
                                
                                    context = {'weather_data': weather_data, 'form': form}
                                
                                    return render(request, 'data/data.html', context)
                                
                                

                                Тоесть просто создал новую модель и все скинул туда.

                                  Evgenii Legotckoi
                                  • 14 января 2019 г. 16:00

                                  Если вы создадите вручную несколько TempUnit, а потом только установка этих TempUnit через выпадающий список, то да, будет даже лучше.

                                  Однако переходите к CBV (Class Based View) вместо обычных вьюшек. Так лучше будет, в будущем оцените.

                                    Arrow
                                    • 14 января 2019 г. 16:46

                                    Спасибо.

                                      Комментарии

                                      Только авторизованные пользователи могут публиковать комментарии.
                                      Пожалуйста, авторизуйтесь или зарегистрируйтесь
                                      AD

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:50баллов,
                                      • Очки рейтинга-4
                                      m
                                      • molni99
                                      • 26 октября 2024 г. 7:37

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:80баллов,
                                      • Очки рейтинга4
                                      m
                                      • molni99
                                      • 26 октября 2024 г. 7:29

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:20баллов,
                                      • Очки рейтинга-10
                                      Последние комментарии
                                      i
                                      innorwall15 ноября 2024 г. 8:27
                                      Релиз утилиты развертывания С++/Qt и QML приложений CQtDeployer v1.4.0 (Binary Box) optionally substituted alkoxy, optionally substituted alkenyloxy, optionally substituted alkynyloxy, optionally substituted aryloxy, OCH, OC H, OC H, OC H, OC H, OC H, OC H, O C CH, OCH CH OH, O…
                                      i
                                      innorwall15 ноября 2024 г. 3:26
                                      Qt/C++ - Урок 031. QCustomPlot - строим график по времени buy generic priligy We can just chat, and we will not lose too much time anyway
                                      i
                                      innorwall15 ноября 2024 г. 1:03
                                      Qt/C++ - Урок 060. Настройка внешнего вида приложения в рантайме I didnt have an issue work colors priligy dapoxetine 60mg revia cost uk August 3, 2022 Reply
                                      i
                                      innorwall14 ноября 2024 г. 17:42
                                      Как Копировать Файлы в Linux If only females relatives with DZ offspring were considered these percentages were 23 order priligy online uk
                                      Сейчас обсуждают на форуме
                                      i
                                      innorwall14 ноября 2024 г. 9:39
                                      добавить qlineseries в функции priligy amazon canada 93 GREB1 protein GREB1 AB011147 6
                                      i
                                      innorwall11 ноября 2024 г. 16:55
                                      Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
                                      9
                                      9Anonim25 октября 2024 г. 15:10
                                      Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
                                      ИМ
                                      Игорь Максимов3 октября 2024 г. 10:05
                                      Реализация навигации по разделам Спасибо Евгений!

                                      Следите за нами в социальных сетях