Django выдает ошибку при наличии нескольких форм в наборах форм при выполнении запроса POST

У меня есть проект django с панелью инструментов и формами с наборами форм, встроенными в администратора django. Я пытаюсь сделать запрос POST из форм в API. У меня есть два набора форм, чтобы быть конкретным. Когда у меня есть более одной формы в любом из наборов форм, я получаю следующую ошибку. Единая форма, однако, проходит. Ниже мой код и ошибка,

Internal Server Error: /admin/campaign/add
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 124, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/views/decorators/cache.py", line 45, in _wrapped_view_func
    add_never_cache_headers(response)
  File "/usr/local/lib/python3.7/site-packages/django/utils/cache.py", line 252, in add_never_cache_headers
    patch_response_headers(response, cache_timeout=-1)
  File "/usr/local/lib/python3.7/site-packages/django/utils/cache.py", line 243, in patch_response_headers
    if not response.has_header('Expires'):
AttributeError: 'NoneType' object has no attribute 'has_header'

формы.py

class CampaignForm(forms.Form):
    consumer = forms.CharField(label = "Consumer", max_length=200)
    startDate = forms.DateTimeField(label = "Start Date",
        input_formats=['%d/%m/%Y %H:%M'])
    endDate = forms.DateTimeField(label = "End Date",
        input_formats=['%d/%m/%Y %H:%M'])
    referreeCredits = forms.IntegerField(label = "Referree Credits")
    referrerCredits = forms.IntegerField(label = "Referrer Credits")
    maxReferreeCredits = forms.IntegerField(label = "Max Referree Credits")
    maxReferrerCredits = forms.IntegerField(label = "Max Referrer Credits")
    message = forms.CharField(label = "Message", max_length=200)
    kramerTemplateId = forms.CharField(label = "Kramer Template ID", max_length=200)
    paymentMode = forms.ChoiceField(label = "Payment Mode", choices=[("PAYTM","PAYTM")])

class RuleForm(forms.Form):
    eventName = forms.CharField(label = "Event Name", max_length=200)
    operator = forms.ChoiceField(label = "Operator", choices=[("EQUAL","EQUAL"), ("EVERY","EVERY")])
    value = forms.IntegerField(label = "Value")

class MilestoneRulesForm(forms.Form):
    operator = forms.ChoiceField(label = "Operator", choices=[("EQUAL","EQUAL"), ("EVERY","EVERY")])
    value = forms.IntegerField(label = "Value")
    referrerCredits = forms.IntegerField(label = "Referrer Credits")

просмотры.py

def campaign_add(self, request):
        form = CampaignForm()
        RuleFormSet = formset_factory(RuleForm)
        MilestoneFormSet = formset_factory(MilestoneRulesForm)
        if request.method == 'POST':
            # import ipdb; ipdb.set_trace()
            form = CampaignForm(request.POST)
            rule_formset = RuleFormSet(request.POST, prefix='rules')
            milestone_formset = MilestoneFormSet(request.POST, prefix='milestones')
            if form.is_valid() and rule_formset.is_valid() and milestone_formset.is_valid():
                    import ipdb; ipdb.set_trace()
                    dat = {}
                    dat["consumer"] = form.cleaned_data["consumer"]
                    dat["startDate"] = self.datetime_to_epoch(form.cleaned_data["startDate"])
                    dat["endDate"] = self.datetime_to_epoch(form.cleaned_data["endDate"])
                    dat["referreeCredits"] = form.cleaned_data["referreeCredits"]
                    dat["referrerCredits"] = form.cleaned_data["referrerCredits"]
                    dat["maxReferreeCredits"] = form.cleaned_data["maxReferreeCredits"]
                    dat["maxReferrerCredits"] = form.cleaned_data["maxReferrerCredits"]
                    dat["message"] = form.cleaned_data["message"]
                    dat["kramerTemplateId"] = form.cleaned_data["kramerTemplateId"]
                    dat["paymentMode"] = form.cleaned_data["paymentMode"]
                    arrRules = rule_formset.cleaned_data
                    arrMilestoneRules = milestone_formset.cleaned_data
                    dat["eventRules"] = arrRules
                    dat["milestoneRules"] = arrMilestoneRules
                    print(rule_formset.cleaned_data)
                    print(milestone_formset.cleaned_data)
                    res = requests.post("https://example.com", data=json.dumps(dat), headers = {'content-type': 'application/json'})
                    if res.status_code == 201 or res.status_code == 200:
                        messages.success(request, 'Success!')
                        return redirect("admin:campaign-pg1")
                    else:
                        messages.error(request, 'Submission Failed.')
        else:
            rule_formset = RuleFormSet(prefix = "rules")
            milestone_formset = MilestoneFormSet(prefix = "milestones")
            return TemplateResponse(request, "admin/campaign_add.html", {"form":form, "rule_formset": rule_formset, "milestone_formset": milestone_formset})

HTML-шаблон:

{% block content %}
    <div class = "form_div" style = "width:60%;">
        <h2>Campaign Form</h2>
        <form method = "POST">
            {% csrf_token %}
            {% for field in form.visible_fields %}
                <div class = "form-group">
                    {{ field.label_tag }}
                    {% render_field field class = "form-control" %}
                    {% if field.help_text %}
                        <small class = "form-text text-muted">{{ field.help_text }}</small>
                    {% endif %}
                </div>
            {% endfor %}            
            <div style = "display: flex; justify-content: space-between; width: 280px;">
                <h3>Rules</h3>
                <button type = "button" id = "generate-rule" class = "btn btn-primary">+</button>
            </div>
            <div class = "parent">
            <div>
            {{ rule_formset.management_form }}
            {% for ruleForm in rule_formset %}
                {{ ruleForm }}
                <input type = "button"  class = "btn btn-warn" style = "background: red;" value = "-">
            {% endfor %}
            </div>
            </div>
             <div style = "display: flex; justify-content: space-between; width: 280px;">
                <h3>Milestone Rules</h3>
                <button  type = "button" id = "generate-milestone-rule" class = "btn btn-primary">+</button>
            </div>
            <div class = "milestone-parent">
            <div>
            {{ milestone_formset.management_form }}
            {% for milestoneForm in milestone_formset %}
                {{ milestoneForm }}
                <input type = "button"  class = "btn btn-warn" style = "background: red;" value = "-">
            {% endfor %}
            </div>
            </div>
            <div>
            <input type = "submit" value = "Post">
            </div>
        </form>
    </div>

    <script>
        $(function () {
            $("#id_startDate").datetimepicker({
            format: 'd/m/Y H:i',
            });
            $("#id_endDate").datetimepicker({
            format: 'd/m/Y H:i',
            });
        });
    </script>

    <script type='text/javascript'>

        const ruleform = `
        <div>
            <label for = "id_rules-{n}-eventName">Event Name:</label>
            <input type = "text" name = "rules-{n}-eventName" maxlength = "200" id = "id_rules-{n}-eventName">

            <label for = "id_rules-{n}-operator">Operator:</label>
            <select name = "rules-{n}-operator" id = "id_rules-{n}-operator">
                <option value = "EQUAL">EQUAL</option>
                <option value = "EVERY">EVERY</option>
            </select>

            <label for = "id_rules-{n}-value">Value:</label>
            <input type = "number" name = "rules-{n}-value" id = "id_rules-{n}-value">
            <input type = "button" class = "btn btn-warn" style = "background: red;" value = "-">
        </div>
        `
        const milestoneform = `
        <div>
            <label for = "id_milestones-{n}-operator">Operator:</label>
            <select name = "milestones-{n}-operator" id = "id_milestones-{n}-operator">
                <option value = "EQUAL">EQUAL</option>
                <option value = "EVERY">EVERY</option>
            </select>

            <label for = "id_milestones-{n}-value">Value:</label>
            <input type = "number" name = "milestones-{n}-value" id = "id_milestones-{n}-value">

            <label for = "id_milestones-{n}-mreferrerCredits">Referrer Credits:</label>
            <input type = "number" name = "milestones-{n}-mReferrerCredits" maxlength = "200" id = "id_milestones-{n}-mReferrerCredits">

            <input type = "button" class = "btn btn-warn" style = "background: red;" value = "-">
        </div>
        `
        $("#generate-rule").on('click', function(e){
            var n = $("#id_rules-TOTAL_FORMS").val(); // current number of forms;
            var new_form = ruleform.replace(/{n}/g, n); // replace all {n} by the new form number
            $(".parent").append(new_form);
            $("#id_rules-TOTAL_FORMS").val(parseInt(n) + 1); // update the total forms number
            console.info($("#id_rules-TOTAL_FORMS").val());
        })
        $("#generate-milestone-rule").on('click', function(e){
             var n = $("#id_milestones-TOTAL_FORMS").val(); // current number of forms;
            var new_form = milestoneform.replace(/{n}/g, n); // replace all {n} by the new form number
            $(".milestone-parent").append(new_form);
            $("#id_milestones-TOTAL_FORMS").val(parseInt(n) + 1); // update the total forms number
            console.info($("#id_milestones-TOTAL_FORMS").val());
        })
        $(".parent").on("click", (e) => {
            //n = $("#id_rules-TOTAL_FORMS").val();
            //$("#id_rules-TOTAL_FORMS").val(parseInt(n)-1);
            //console.info($("#id_rules-TOTAL_FORMS").val());
            return e.target.classList.contains('btn-warn') && e.target.parentNode.remove()
        })

        $(".milestone-parent").on("click", (e) => {
            //n = $("#id_milestones-TOTAL_FORMS").val();
            //$("#id_milestones-TOTAL_FORMS").val(parseInt(n)-1);
            //console.info($("#id_milestones-TOTAL_FORMS").val());
            return e.target.classList.contains('btn-warn') && e.target.parentNode.remove()
        })
    </script>
{% endblock %}

Как мне решить эту ошибку, чтобы я мог сделать запрос POST с любым количеством форм в моих наборах форм?

Редактировать: Вот так выглядит мой набор форм. Когда у меня есть более одной формы, я получаю указанную выше ошибку. мои наборы форм

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
115
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

может быть, вы достигли состояния, когда код состояния вашего запроса недействителен (не 200 или 201)? В этом случае вы не возвращаете никакого ответа, который вы просто звоните:

else:
    messages.error(request, 'Submission Failed.')

Трассировка стека вашего исключения предполагает, что объекта ответа нет (вы не возвращаете никакого ответа из представления)

File "/usr/local/lib/python3.7/site-packages/django/utils/cache.py", line 243, in patch_response_headers
    if not response.has_header('Expires'):
AttributeError: 'NoneType' object has no attribute 'has_header'

Проверьте, почему вызов API не работает, и решите проблему, после чего вы сможете отправить свою форму.

Привет. Но почему я получаю сообщение об ошибке, когда у меня есть более одной формы в правилах и правилах вех, тогда как запрос выполняется, когда у меня есть только одна форма в одном и том же.

Mohnish M 08.04.2019 11:34

Похоже, что большинство ваших полей формы являются обязательными полями. Возможно, если у вас есть более одной формы, вы отправляете пустые формы, которые не проходят проверку. Единственный способ узнать это — посмотреть на все ваши атрибуты formsets['errors'] (с помощью pdb или с оператором печати), а также на атрибут form['errors']

matyas 08.04.2019 11:40

По умолчанию formset_factory() определяет одну дополнительную форму. Количество отображаемых пустых форм управляется дополнительным параметром.

MilestoneFormSet = formset_factory(MilestoneForm, extra=2)
RuleFormSet = formset_factory(RuleForm, extra=2)

Другие вопросы по теме