Django Form clean видит объекты Date как NoneType. Метод POST в views.py считает его датой - PullRequest
0 голосов
/ 01 апреля 2019

Так что я сейчас работаю над проектом в Джанго. Пользователь должен иметь возможность установить дату начала и дату окончания, на основе этого установленного интервала анализ должен быть рассчитан.

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

Примечание: я не загружал весь HTML-код. Только сформируйте соответствующий код.

forms.py

from django import forms
from tempus_dominus.widgets import DatePicker
import datetime


class AnalysisInformationForm(forms.Form):
    start = forms.DateField(help_text="Enter a date between 2019-03-01 and now.",
                            input_formats=["%d/%m/%Y"],
                            widget=DatePicker(
                                options={
                                    'minDate': '2019-03-01',
                                    'maxDate': datetime.datetime.utcnow().date().strftime("%Y-%m-%d")
                                })
                            )
    end = forms.DateField(help_text="Enter a date between the chosen start date and now",
                          input_formats=["%d/%m/%Y"],
                          widget=DatePicker(
                              options={
                                  'minDate': '2019-03-01',
                                  'maxDate': datetime.datetime.utcnow().date().strftime("%Y-%m-%d")
                              })
                          )

    def clean(self):
        cleaned_data = super(AnalysisInformationForm, self).clean()
        start = cleaned_data.get('start')
        end = cleaned_data.get('end')
        print(start, end)
        if start >= end:
            raise forms.ValidationError('Invalid dates input. The start day must be set earlier than the end date. ')
        return cleaned_data

views.py

def index(request):
    if request.method == 'POST':
        form = AnalysisInformationForm(request.POST)
        if form.is_valid():
            pass
    else:
        form = AnalysisInformationForm()
    return render(request, 'stm/index.html', {'form': form})

index.html

<head>
        <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css">
        <link rel="stylesheet" href="{%  static 'css/bootstrap.css' %}"><link>
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
</head>
        {{ form.media }}
<body>
<div class="form-group"></div>
                        {% load widget_tweaks %}
                        <form method="post" novalidate>
                            {% csrf_token %}

                            {% for hidden_field in form.hidden_fields %}
                                {{ hidden_field }}
                            {% endfor %}

                            {% if form.non_field_errors %}
                                <div class="alert alert-danger" role="alert">
                                  {% for error in form.non_field_errors %}
                                    {{ error }}
                                  {% endfor %}
                                </div>
                            {% endif %}

                            {% for field in form.visible_fields %}
                                <div class="input-group">
                                {{ field.label_tag }}
                                {% if form.is_bound %}
                                    {% if field.errors %}
                                        {% render_field field class="form-control is-invalid" %}
                                        {% for error in field.errors %}
                                            <div class="invalid-feedback">
                                              {{ error }}
                                            </div>
                                        {% endfor %}
                                    {% else %}
                                        {% render_field field class="form-control is-valid" %}
                                    {% endif %}
                                {% else %}
                                    {% render_field field class="form-control" %}
                                {% endif %}
                                {% if field.help_text %}
                                    <small class="form-text text-muted">{{ field.help_text }}</small>
                                {% endif %}
                                </div>
                            {% endfor %}
                            <div class="input-group m-3">
                                <input type="submit" class="btn btn-outline-secondary btn-block" value="Continue">
                            </div>
                        </form>
</body>

Эти уроки привели меня к этому решению:

https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html#rendering-bootstrap-4-forms

https://pypi.org/project/django-tempus-dominus/

https://pypi.org/project/django-widget-tweaks/

Я также нашел похожий вопрос о переполнении стека, хотя ответа не было: Форма Django DateField генерирует None в cleaned_data

Я также попытался сделать следующее, чтобы проверить, поступают ли реальные данные. поэтому в views.py я изменил следующее: До:

form = AnalysisInformationForm(request.POST)

После того, как:

form = request.POST['start']
print(form)

В промежутке между ошибками я обнаружил это утверждение для печати. И сюрприз, сюрприз, данная дата начала действительно соответствует фактическим данным. Но после очистки данные становятся значением NoneType.

Есть предложения, что может быть причиной?

Ожидаемый результат - данные будут проверены, как показано в коде. Дата начала должна быть установлена ​​раньше, чем дата окончания, и если не отображается сообщение об ошибке.

Ответы [ 4 ]

0 голосов
/ 02 апреля 2019

Итак, попробовав несколько вещей.Я пришел к следующему решению: во-первых, в forms.py я обновил функцию clean, чтобы соответствовать следующему.Нашел эту чистую функцию где-то здесь на stackoverflow, но забыл сохранить ссылку на нее, не знал, сработает ли она:

    def clean(self):
        data = self.cleaned_data
        print(data)
        start = data.get('start')
        end = data.get('end')
        if start >= end:
            raise forms.ValidationError('Invalid dates input. The start day must be set earlier than the end date. ')
        return data

Затем я попробовал несколько форматов ввода даты, например ["% y/% m /% d "] (формат 19/04/02, не iso), ["% Y /% m /% d "] (формат 2019/04/02, не iso), ["% y-%m-% d "] (формат 19-04-02, не iso), ["% Y-% m-% dT% H:% M:% S.% fZ "] (хорошо, формат даты-времени iso, но яработаю с объектами даты, а не объектами даты и времени).Итак, я пришел к выводу, что мне просто нужно изменить / на - в ["% Y /% m /% d"], и все должно работать.И это действительно сработало: D

Вот так выглядит новый обновленный класс форм:

class AnalysisInformationForm(forms.Form):
    start = forms.DateField(help_text="Enter a date between 2019-03-01 and now.",
                            input_formats=["%Y-%m-%d"],
                            widget=DatePicker(
                                options={
                                    'minDate': '2019-03-01',
                                    'maxDate': datetime.datetime.utcnow().date().strftime("%Y-%m-%d")
                                })
                            )
    end = forms.DateField(help_text="Enter a date between the chosen start date and now",
                          input_formats=["%Y-%m-%d"],
                          widget=DatePicker(
                              options={
                                  'minDate': '2019-03-01',
                                  'maxDate': datetime.datetime.utcnow().date().strftime("%Y-%m-%d")
                              })
                          )

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

0 голосов
/ 01 апреля 2019

для Django 2.1 попробуйте это

def clean(self):
    cleaned_data = super().clean()
    start = cleaned_data.get("start")
    end = cleaned_data.get("end")

надеюсь, это поможет

0 голосов
/ 01 апреля 2019

Попытайтесь найти то, что передано методу clean () перед вызовом super ().Возможно, он исходит от клиента в формате, отличном от iso, и не прошел проверку по умолчанию из суперкласса

0 голосов
/ 01 апреля 2019

может быть, вам нужно сделать "пост" в HTML все заглавные буквы

 <form method="POST" novalidate>
...