Django formsets没有发布数据
Posted
技术标签:
【中文标题】Django formsets没有发布数据【英文标题】:Django formsets no data on post 【发布时间】:2015-11-24 17:02:09 【问题描述】:我有一个使用多个表单集的表单。 formset表单是通过JS动态添加的。我一直在寻找几个不同的地方来帮助自己。
Add a dynamic form to a django formset using javascript in a right way
和
A nice post by Kevin Dias - Django class-based views with multiple inline formsets
我遇到的问题是,当我发布数据时,外部表单有数据,但是当我开始循环遍历它们时,我的表单集实际上没有任何数据在 clean_data 字典中。关于我可能遗漏的任何想法?第二个formset添加了一个非常相似的JS方法。
表格
class ShippingForm(Form):
is_partial = BooleanField(label='Partial?')
class ShippingActualProduct(Form):
box_no = CharField(label='Box Number', max_length=3)
upc = CharField(
widget=forms.TextInput(attrs='class':'upcAjax'),
)
serial_no = CharField(
label='Serial Number',
widget=forms.TextInput(attrs='class':'serial'),
)
sku = CharField(
widget=forms.TextInput(attrs='class':'skuAjax'),
)
description=CharField(label='Description')
on_hand=CharField(label='On Hand')
def __init__(self, *args, **kwargs):
super(ShippingActualProduct,self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_show_labels = True
self.helper.form_class = 'form-inline'
class ShippingNonInventoryProduct(Form):
non_box_no = CharField(label='Box Number', max_length=3)
quantity = IntegerField()
description = CharField()
serial_no = CharField()
def __init__(self, *args, **kwargs):
super(ShippingNonInventoryProduct,self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_show_labels = True
self.helper.form_class = 'form-inline'
ActualProductFormSet = formset_factory(ShippingActualProduct, extra=1, can_delete=True)
NonInventoryProductFormSet = formset_factory(ShippingNonInventoryProduct, extra=1, can_delete=True)
观看次数
class ShippingCreate(FormView):
template_name = 'jinja2/Shipping/shipping_create.html'
form_class = ShippingForm
success_url = reverse_lazy('shipping_create')
def get_context_data(self, **kwargs):
context = super(ShippingCreate, self).get_context_data(**kwargs)
input_invoice_no = self.request.GET['invoice_no']
try:
self.object = Invoice.objects.get(invoice_no = input_invoice_no)
context['invoice'] = self.object
except Invoice.DoesNotExist:
messages.error(self.request, 'We were unable to find invoice number %s, please try again' % input_invoice_no)
try:
context['voucher'] = Voucher.objects.get(voucher_no = self.object.voucher_no)
except Voucher.DoesNotExist:
messages.error(self.request, 'We were unable to find an installation voucher for claim number %s' % self.object.voucher_no)
context['actual_items_forms'] = ActualProductFormSet(prefix='actual')
context['non_inventory_items_forms'] = NonInventoryProductFormSet(prefix='non')
context['form'] = ShippingForm()
return context
def get(self, request, *args, **kwargs):
self.object = None
context = self.get_context_data()
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
actual_product = ActualProductFormSet(self.request.POST, prefix='actual')
non_inv_product = NonInventoryProductFormSet(self.request.POST, prefix='non')
if actual_product.is_valid():
for product in actual_product:
data = product.cleaned_data
sku = data.get('sku')
context=
return render(request, self.template_name, context)
模板
% extends "base.html" %
% load crispy_forms_tags %
% load static from staticfiles %
% load socialaccount %
% load sitetree %
% block headcss %
block.super
<link rel="stylesheet" href="% static "css/shipping.css" %">
% endblock headcss %
% block headjs %
block.super
<script src="% static "js/shipping.js" %"></script>
% endblock headjs %
% block content %
% block messages %
block.super
% endblock messages %
<div class="container-fluid">
<form action="." method="post">
<div>
<h3>Item information:</h3>
% csrf_token %
actual_items_forms.management_form
<div id="actual-items-form-container">
</div>
<a href="#" id="actual-item-btn" class="btn btn-info fa fa-plus-square add-item"> Add Item</a>
</div>
<div>
<h3>Non Inventory Items Shipped:</h3>
non_inventory_items_forms.management_form
<div id="non-inv-items-form-container">
</div>
<a href="#" id="add-non-inv-item-btn" class="btn btn-info fa fa-plus-square add-non-item"> Add Item</a>
</div>
form.as_p
<input type="submit" value="Complete" class="submit btn btn-success" />
</form>
</div>
% include "jinja2/hub/loading_modal.html" %
% endblock content %
</html>
JavaScript
function getNewActualItemForm()
// unbind this ajax call from the overlay displayed when looking data up.
$(document).unbind(".items");
var count = $('#actual-items-form-container').children().length;
$.get("/forms/actualitemform",function(data, status)
var form = data.replace(/__prefix__/g, count);
// Get the html contents of the form, all together to iterate over.
var htmlForm = $('<form>').html(form).contents();
// Just grab the children of that form
var rows = htmlForm.children();
// loop through the inputs locating the DELETE input and label.
$(rows).each( function(index, value)
var row = $(this);
var del = $(row).find('input:checkbox[id $= "-DELETE"]');
// Only move forward if we have found the DELETE input
if (del.length)
//Write the form ot the Dom so the search for the label will succeed.
$('div#actual-items-form-container').append(form);
var label ='label[for="id_form-' + count + '-DELETE"]';
$(label).hide();
);
// update form count
$('#id_actual-TOTAL_FORMS').attr('value', count+1);
// some animate to scroll to view our new form
$('html, body').animate(
scrollTop: $('#actual-item-btn').position().top-200
, 800);
// get the max box number.
var maxBoxNo = getBoxNo();
// Set focus to the next UPC
var boxID = '#id_form-var-box_no';
var upcID = '#id_form-var-upc';
var nextBox = boxID.replace('var',count);
var nextUpc = upcID.replace('var',count);
// set the box number for the new line.
$(nextBox).val(maxBoxNo);
$(nextUpc).focus();
);
return count;
【问题讨论】:
你怎么知道的?您的post
方法不会对清理后的数据执行任何操作,也不会将无效表单返回到模板。
对不起丹尼尔,我应该指定的。我使用 Pycharm 并使用他们的调试器逐步执行代码。这就是我停止在 Post 上继续前进的原因,因为我在表单集方面没有得到任何回报。
【参考方案1】:
这里有两个问题造成了麻烦。
-
我让脆皮表单助手为每个表单集呈现表单标签。这是一个坏主意。设置 form_tag = False 解决了这个问题。
我忘记在我创建的视图中为我的表单集设置前缀参数,以便通过 JavaScript 获取下一个表单。
一旦实现了这两个,数据现在可以从提交的表单中获得。
【讨论】:
以上是关于Django formsets没有发布数据的主要内容,如果未能解决你的问题,请参考以下文章
Django CBV - Formsets:'NoneType'对象没有属性'id'