django - inlineformset_factory:验证失败(此字段为必填项)
问题描述
我有带有 3 个字段的 inlineformset_factory 表单。
但是当我更新表单时,会创建一个新的空白行。
如果我决定将此行留空,则验证失败,因为需要字段
所以问题来自 inlineformset_factory MenuFormset 中的“额外”参数。我考虑过使用带有 extra=0 的特定 inlineformset_factory UpdateMenuFormset 用于更新视图,但这可能不是一个好方法;此外,当我添加一个表单集时,它会使用预填充值而不是空表单集进行表单设置...
如何管理此验证?
模型.py
class Orders(SafeDeleteModel):
""" A class to create a new order instance in the Schitt's Creek Cafe Tropical. """
_safedelete_policy = SOFT_DELETE_CASCADE
order_id = models.AutoField("Order id", primary_key = True)
table = models.ForeignKey(Tables, on_delete = models.CASCADE) # related table
customers = models.IntegerField("Number of customer", null=True, blank=True)
split_bill = models.IntegerField("Split bill", null=True, blank=True)
delivered = models.BooleanField("Delivered", null=True, blank=True, default=False)
paid = models.BooleanField("Available", null=True, blank=True, default=False)
created_at = models.DateTimeField("Date created", auto_now_add = True)
log = HistoricalRecords()
class Orders_Menus(SafeDeleteModel):
""" A class to create a new Orders_Menus instance in the Schitt's Creek Cafe Tropical. """
_safedelete_policy = SOFT_DELETE_CASCADE
order = models.ForeignKey("Orders", on_delete = models.CASCADE)
menu = models.ForeignKey("Menus", on_delete = models.CASCADE)
cooking = models.IntegerField("Cooking", default=0, null=True, blank=True)
tone = models.IntegerField("Tone", default=0, null=True, blank=True)
log = HistoricalRecords()
class Meta:
db_table = 'Orders_Menus'
表格.py
MenuFormset = inlineformset_factory(
Orders, Orders_Menus,
fields=('cooking','menu','tone'),
widgets={
'cooking': forms.Select(choices = COOKING),
'tone': forms.Select(choices = TONES),
'menu': forms.Select(choices = MENUS),
},
extra=1,
can_delete=True,
)
order_update.html
{% extends 'layouts/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block extrahead %}{% endblock %}
{% block title %}Order | Schitt's Creek Cafe Tropical{% endblock %}
{% block content %}
<style>
.addspace {
padding-bottom:10px;
}
</style>
<div class='container'>
<br>
<br>
<h1>Complete order - Update</h1>
<br>
<br>
<br>
<form id="ordereditform" method="POST" class="post-form">
{% csrf_token %}
{{ form|crispy }}
{% comment %} <a style="margin-right: 40px" data-target="" class="" href="#">New Menu</a> {% endcomment %}
<br>
<div class="dropdown-divider"></div>
<h2>Menus</h2><br><br>
<!-- {{ menu|crispy }} --> <!-- curieusement si j'enlève cette ligne le style crispy disparait -->
{{ menu.management_form|crispy }}
{% if menu.non_form_errors %}
<div id="non_form_errors" class="alert alert-block alert-danger" >
{% for error in menu.non_form_errors %}
<ul>
<li>{{ error|escape }}</li>
</ul>
{% endfor %}
</div>
{% endif %}
<div class="row">
<div class="col-4"><p>Item</p></div>
<div class="col-3"><p>Cooking</p></div>
<div class="col-4"><p>Tone</p></div>
<div class="col-1"><p></p></div>
</div>
{% for menu_form in menu %}
<div class="row link-formset addspace">
<div class="col-4">
{{ menu_form.menu }}
{% if menu_form.menu.errors %}
{% for error in menu_form.menu.errors %}
<span style="color:red;">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
{% if menu_form.instance.pk %}{{ menu_form.DELETE }}{% endif %}
<div class="col-3">
{{ menu_form.cooking }}
{% if menu_form.cooking.errors %}
{% for error in menu_form.cooking.errors %}
<span style="color:red;">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
<div class="col-4">
{{ menu_form.tone }}
{% if menu_form.tone.errors %}
{% for error in menu_form.tone.errors %}
<span style="color:red;">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
<div class="hidden">{{ menu_form.id }}</div>
</div>
{% endfor %}
<br><br>
<button id="ajouter_projet" class="btn btn-primary" type="submit" style="width: 100px;">Save</button>
<a data-modal data-target="" class="btn btn-danger" href="{% url 'cafe:index' %}" style="width: 100px;">Cancel</a>
</form>
<!-- Modal -->
<div class="modal fade" id="order_edit" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Schitt's Creek Cafe Tropical</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Do you valid order?
</div>
<div class="modal-footer">
<button id="order_button_no" type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<button id="order_button_yes" data-redirect-url="" type="button" class="btn btn-primary">Yes</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extrabody %}
<!--DataTable-->
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css">
<!--DataTable-->
<!--Modal-->
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<!--Modal-->
<script src="{% static 'cafe/js/jquery.formset.js' %}"></script>
<script type="text/javascript">
var popup_order;
var menunumber_subform; // nombre de sous formulaire affichés (1 par défaut puis ajout sur click .add-row)
var select_app;
var select_access;
$('.link-formset').formset({
addText: 'Add',
deleteText: 'Delete',
prefix: '{{ menu.prefix }}',
//hideLastAddForm: 'true',
});
$(document).ready(function() {
var prevent = false;
var menunumber_subform = menunumber(); // nombre de sous formulaire affichés (1 par défaut au chargement de la page)
var menuinitialnumber_subform = menuinitialnumber();
// to add empty formset (by default, it clone previous frormset with its values)
$('.add-row').on('click',function(event){
i = menuinitialnumber_subform;
$('#id_orders_menus_set-'+i+'-menu').val('');
$('#id_orders_menus_set-'+i+'-cooking').val('');
$('#id_orders_menus_set-'+i+'-tone').val('');
menuinitialnumber_subform++;
})
$("#ordereditform").submit(function(event) {
if(!prevent){
event.preventDefault();
}
popup_order = $(this);
$('#order_edit').modal('show');
});
$("body")
.on('click','#order_button_yes',function(event){
prevent = true;
popup_order.submit();
})
});
// déterminer le nombre de sous-formulaire menu présents sur la page
function menunumber() {
return $("#id_orders_menus_set-TOTAL_FORMS").val();
};
// déterminer le nombre de sous-formulaire menu présents sur la page
function menuinitialnumber() {
return $("#id_orders_menus_set-INITIAL_FORMS").val();
};
</script>
{% endblock %}
order_edit.html
{% extends 'layouts/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block extrahead %}{% endblock %}
{% block title %}Order | Schitt's Creek Cafe Tropical{% endblock %}
{% block content %}
<style>
.addspace {
padding-bottom:10px;
}
</style>
<div class='container'>
<br>
<br>
<h1>Complete order</h1>
<br>
<br>
<br>
<form id="ordereditform" method="POST" class="post-form" data-tables="{{ tables }}">
{% csrf_token %}
{{ form|crispy }}
{% comment %} <a style="margin-right: 40px" data-target="" class="" href="#">New Menu</a> {% endcomment %}
<br>
<div class="dropdown-divider"></div>
<h2>Menus</h2><br><br>
<!-- {{ menu|crispy }} --> <!-- curieusement si j'enlève cette ligne le style crispy disparait -->
{{ menu.management_form|crispy }}
{% if menu.non_form_errors %}
<div id="non_form_errors" class="alert alert-block alert-danger" >
{% for error in menu.non_form_errors %}
<ul>
<li>{{ error|escape }}</li>
</ul>
{% endfor %}
</div>
{% endif %}
<div class="row">
<div class="col-4"><p>Item</p></div>
<div class="col-3"><p>Cooking</p></div>
<div class="col-4"><p>Tone</p></div>
<div class="col-1"><p></p></div>
</div>
{% for menu_form in menu %}
<div class="row link-formset addspace">
<div class="col-4">
{{ menu_form.menu }}
{% if menu_form.menu.errors %}
{% for error in menu_form.menu.errors %}
<span style="color:red;">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
{% if menu_form.instance.pk %}{{ menu_form.DELETE }}{% endif %}
<div class="col-3">
{{ menu_form.cooking }}
{% if menu_form.cooking.errors %}
{% for error in menu_form.cooking.errors %}
<span style="color:red;">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
<div class="col-4">
{{ menu_form.tone }}
{% if menu_form.tone.errors %}
{% for error in menu_form.tone.errors %}
<span style="color:red;">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
<div class="hidden">{{ menu_form.id }}</div>
</div>
{% endfor %}
<br><br>
<button id="ajouter_projet" class="btn btn-primary" type="submit" style="width: 100px;">Save</button>
<a data-modal data-target="" class="btn btn-danger" href="{% url 'cafe:index' %}" style="width: 100px;">Cancel</a>
</form>
<!-- Modal -->
<div class="modal fade" id="order_edit" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Schitt's Creek Cafe Tropical</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Do you valid order?
</div>
<div class="modal-footer">
<button id="order_button_no" type="button" class="btn btn-secondary" data-dismiss="modal">No</button>
<button id="order_button_yes" data-redirect-url="" type="button" class="btn btn-primary">Yes</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extrabody %}
<!--DataTable-->
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css">
<!--DataTable-->
<!--Modal-->
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<!--Modal-->
<script src="{% static 'cafe/js/jquery.formset.js' %}"></script>
<script type="text/javascript">
var popup_order;
var menunumber_subform; // nombre de sous formulaire affichés (1 par défaut puis ajout sur click .add-row)
var select_app;
var select_access;
$('.link-formset').formset({
addText: 'Add',
deleteText: 'Delete',
prefix: '{{ menu.prefix }}',
//hideLastAddForm: 'true'
});
$(document).ready(function() {
var prevent = false;
var menunumber_subform = menunumber(); // nombre de sous formulaire affichés (1 par défaut au chargement de la page)
var tables = {{ tables }}
//https://codepen.io/Lighty_46/pen/gpLZWx?editors=1010
// When an option is changed, search the above for matching choices
$('#id_table').on('change', function() {
// Set selected option as variable
var selectValue = $(this).val();
// Empty the target field
$('#id_customers').empty();
// For each choice in the selected option
for (i = 0; i < tables[selectValue].length; i++) {
// Output choice in the target field
$('#id_customers').append("<option value='" + tables[selectValue][i] + "'>" + tables[selectValue][i] + "</option>");
}
});
$("#ordereditform").submit(function(event) {
if(!prevent){
event.preventDefault();
}
popup_order = $(this);
$('#order_edit').modal('show');
});
$("body")
.on('click','#order_button_yes',function(event){
prevent = true;
popup_order.submit();
})
});
// déterminer le nombre de sous-formulaire menu présents sur la page
function menunumber() {
return $("#id_orders_menus_set-TOTAL_FORMS").val();
};
</script>
{% endblock %}
解决方案
推荐阅读
- sql-server - SSRS - 如何将日期/时间参数的格式设置为 yyyy-mm-dd hh:mm:ss?
- c# - 注册表项 EditionID 在 WOW6432Node 下的值错误 - 有意还是错误?如何绕过?
- php - 如何在从 fpdm(Fpdf) 库类生成的 PDF 中设置密码?
- angular - 使用搜索栏过滤 Firebase 列表时出错
- powerapps - PowerApps:如何使用 1:N 关系修补多个 CDS 实体?
- oop - 我们认为模型与 MVVM(应用于 JavaFX)的关系是什么?
- python - 使用 drop 方法后行出现在我的情节中
- c# - 如何从工具提示中定位和获取文本?
- c# - 如何在库保护类中包含使用?
- javascript - 如何使用角度自定义管道对数组内的嵌套对象进行排序?