У меня есть проект 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 с любым количеством форм в моих наборах форм?
Редактировать: Вот так выглядит мой набор форм. Когда у меня есть более одной формы, я получаю указанную выше ошибку. мои наборы форм
может быть, вы достигли состояния, когда код состояния вашего запроса недействителен (не 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 не работает, и решите проблему, после чего вы сможете отправить свою форму.
Похоже, что большинство ваших полей формы являются обязательными полями. Возможно, если у вас есть более одной формы, вы отправляете пустые формы, которые не проходят проверку. Единственный способ узнать это — посмотреть на все ваши атрибуты formsets['errors'] (с помощью pdb или с оператором печати), а также на атрибут form['errors']
По умолчанию formset_factory() определяет одну дополнительную форму. Количество отображаемых пустых форм управляется дополнительным параметром.
MilestoneFormSet = formset_factory(MilestoneForm, extra=2)
RuleFormSet = formset_factory(RuleForm, extra=2)
Привет. Но почему я получаю сообщение об ошибке, когда у меня есть более одной формы в правилах и правилах вех, тогда как запрос выполняется, когда у меня есть только одна форма в одном и том же.