modelformset_factory错误
“禁止在未明确定义“字段”或“排除”的情况下调用modelformset_factory。”
我想创建一个动态表单,其中包含多个使用jQuery添加或删除的输入字段。但是当我尝试运行代码时出现错误。我把代码写下来了,请检查并帮助我解决这个问题。 谢谢
我遵循一个教程和Github代码。这是链接
Youtube: https://www.youtube.com/watch?v=Tg6Ft_ZV19M
Github代码: https://github.com/shitalluitel/formset
views.py
def acc_journal(request):
journalEntryFormset = modelformset_factory(
AccountsJournalVoucherEntery, form=AccountsPymtVoucherForm)
form = AccountJournalVoucherForm(request.POST or None)
journalEntryset = journalEntryFormset(
request.POST or None, queryset=AccountsJournalVoucherEntery.objects.none(), prefix='journalentries')
if request.method == 'POST':
if form.is_valid() and journalEntryset.is_valid():
try:
with transaction.atomic():
journalvc = form.save(commit=False)
journalvc.save()
for journalEntry in journalEntryset:
entery = journalEntry.save(commit=False)
entery.journalvc = journalvc
entery.save()
except IntegrityError:
print('Error Encountered')
return redirect('accunts-journal')
context = {
'acc_journal_acti': 'active',
'main_header': 'Accounts',
'header_heading': 'Journal',
'acc_journals': Accounts_journal_voucher.objects.all(),
'form': form,
'formset': journalEntryset
}
return render(request, 'accounts/journal.html', context)
model.py
class Accounts_journal_voucher(models.Model):
journal_voucher_id = models.AutoField(primary_key=True)
acc_jurnl_vc_num = models.CharField(max_length=50, blank=False)
acc_jurnl_vc_loc = models.CharField(max_length=50, blank=False)
acc_jurnl_vc_date = models.DateField(auto_now=False)
acc_jurnl_vc_ref_num = models.CharField(max_length=50, blank=True)
acc_jurnl_vc_total_debit = models.DecimalField(
max_digits=30, decimal_places=2, blank=True, null=True)
acc_jurnl_vc_total_credit = models.DecimalField(
max_digits=30, decimal_places=2, blank=True, null=True)
acc_jurnl_vc_info = models.TextField(blank=True)
acc_jurnl_vc_added_by = models.CharField(max_length=200, blank=True)
acc_jurnl_vc_date_added = models.DateTimeField(
default=datetime.now, blank=True)
def __str__(self):
return self.acc_jurnl_vc_num
class AccountsJournalVoucherEntery(models.Model):
ajve_id = models.AutoField(primary_key=True)
ajve_journal_vc = models.ForeignKey(
Accounts_journal_voucher, related_name='journalvc', on_delete=models.CASCADE)
ajve_group = models.CharField(max_length=200)
ajve_account = models.CharField(max_length=200)
ajve_location = models.CharField(max_length=200, default='')
ajve_narration = models.CharField(max_length=200, default='')
ajve_currency = models.CharField(max_length=100)
ajve_ex_rate = models.IntegerField()
ajve_debit_amt = models.DecimalField(
max_digits=99, decimal_places=2, default='')
ajve_credit_amt = models.DecimalField(
max_digits=99, decimal_places=2, default='')
ajve_debit_base = models.DecimalField(
max_digits=99, decimal_places=2, default='')
ajve_credit_base = models.DecimalField(
max_digits=99, decimal_places=2, default='')
ajve_balance = models.DecimalField(
max_digits=99, decimal_places=2, default='')
ajve_added_by = models.CharField(max_length=200, blank=True)
ajve_date_added = models.DateTimeField(
default=datetime.now, blank=True)
def __str__(self):
return self.ajve_journal_vc
forms.py
class AccountJournalVoucherForm(forms.Form):
acc_jurnl_vc_num = forms.CharField(label='Voucher Number', initial='JRNL-000369', required=True, widget=forms.TextInput(
attrs={
'class': 'form-control'
}
))
acc_jurnl_vc_loc = forms.CharField(label='Location', required=True, widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'LOCATION'
}
))
acc_jurnl_vc_date = forms.DateField(label='Date', required=True, widget=forms.DateInput(
attrs={
'class': 'form-control datepicker',
'placeholder': '2020-01-12'
}
))
acc_jurnl_vc_ref_num = forms.CharField(label='Reference No', required=False, widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'REFERENCE NUMBER',
}
))
acc_jurnl_vc_total_debit = forms.DecimalField(label='Total Debit', disabled=True, widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
acc_jurnl_vc_total_credit = forms.DecimalField(label='Total Credit', disabled=True, widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
acc_jurnl_vc_info = forms.CharField(label='Info', required=False, widget=forms.Textarea(
attrs={
'class': 'form-control',
'placeholder': 'Enter info....'
}
))
class AccountsPymtVoucherForm(forms.Form):
accountLedger = Accounts_ledger.objects.all().order_by('accunt_ledgr_under')
accountGroup = Accounts_group.objects.all().order_by('accunt_group_under')
allAccounts = accountLedger and accountGroup
ajve_group = forms.ChoiceField(label='Group', required=True, choices=Accountschoices, widget=forms.Select(
attrs={
'class': 'form-control',
}
))
ajve_account = forms.ModelChoiceField(label='Account', required=True, queryset=allAccounts, empty_label='SELECT ACCOUNT', widget=forms.Select(
attrs={
'class': 'form-control'
}
))
ajve_location = forms.ChoiceField(label='Location', required=True, choices=(('Main', 'Main'), ('Abu Dhabi', 'Abu Dhabi')), widget=forms.Select(
attrs={
'class': 'form-control'
}
))
ajve_narration = forms.CharField(label='Narration', required=False, widget=forms.TextInput(
attrs={
'class': 'form-control'
}
))
ajve_currency = forms.ModelChoiceField(label='Currency', required=True, queryset=Master_currency.objects.all().order_by('currency_name'), widget=forms.Select(
attrs={
'class': 'form-control'
}
))
ajve_ex_rate = forms.IntegerField(label='EX. Rate', required=True, widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
ajve_debit_amt = forms.DecimalField(label_suffix='Dr. Amount', widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
ajve_credit_amt = forms.DecimalField(label_suffix='Cr. Amount', widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
ajve_debit_base = forms.DecimalField(label_suffix='Dr. Base', widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
ajve_credit_base = forms.DecimalField(label_suffix='Cr. Base', widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
ajve_balance = forms.DecimalField(label_suffix='Balance', widget=forms.NumberInput(
attrs={
'class': 'form-control'
}
))
HTML模板
{% load crispy_forms_tags %}
<form method="POST">
{% csrf_token %}
<fieldset>
<div class="row">
<div class="form-group">
<div class="col-md-3 col-sm-6 col-xs-12">
{{ form.acc_jurnl_vc_num|as_crispy_field }}
</div>
<div class="col-md-3 col-sm-6 col-xs-12">
{{ form.acc_jurnl_vc_date|as_crispy_field }}
</div>
<div class="col-md-3 col-sm-6 col-xs-12">
{{ form.acc_jurnl_vc_loc|as_crispy_field }}
</div>
<div class="col-md-3 col-sm-6 col-xs-12">
{{ form.acc_jurnl_vc_ref_num|as_crispy_field }}
</div>
</div>
</div>
</fieldset>
<br>
<br>
<div class="col-md-12 col-sm-12 col-xs-12">
{% for entries in formset %}
<div class="row">
<div class="form-group">
<div class="col-md-3 col-sm-4 col-xs-12">
{{ entries.ajve_group|as_crispy_field }}
</div>
<div class="col-md-3 col-sm-4 col-xs-12">
{{ entries.ajve_account|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_location|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_narration|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_currency|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_ex_rate|as_crispy_field }}
</div>
<div class="col-md-1 col-sm-4 col-xs-12">
{{ entries.ajve_debit_amt|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_credit_amt|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_debit_base|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_credit_base|as_crispy_field }}
</div>
<div class="col-md-2 col-sm-4 col-xs-12">
{{ entries.ajve_balance|as_crispy_field }}
</div>
<div class="col-md-1 col-sm-4 col-xs-12">
<button class="btn btn-sm btn-danger remove-form-row" id="{{ formset.prefix }}">X</button>
</div>
<div class="col-md-1 col-sm-4 col-xs-12">
<button class="btn btn-sm btn-success add-form-row" id="{{ formset.prefix }}">Add</button>
</div>
</div>
</div>
{% endfor %}
</div>
{{ formset.management_form }}
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<button type="submit" name="submit" class="btn btn-featured btn-blue btn-inverse margin-top-30">
<span>SAVE NEW JOURNAL VOUCHER</span>
<i class="et-book-open"></i>
</button>
</div>
</div>
</form>
jQuery脚本
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+-)');
var replacement = prefix + '-' + ndx + '-';
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex,
replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
if (formCount < 1000) {
// Clone a form (without event handlers) from the first form
var row = $(".item:last").clone(false).get(0);
// Insert it after the last form
$(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);
// Remove the bits we don't want in the new row/form
// e.g. error messages
$(".errorlist", row).remove();
$(row).children().removeClass("error");
// Relabel or rename all the relevant bits
$(row).find('.formset-field').each(function () {
updateElementIndex(this, prefix, formCount);
$(this).val('');
$(this).removeAttr('value');
$(this).prop('checked', false);
});
// Add an event handler for the delete item/form link
$(row).find(".delete").click(function () {
return deleteForm(this, prefix);
});
// Update the total form count
$("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1);
} // End if
return false;
}
function deleteForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
if (formCount > 1) {
// Delete the item/form
var goto_id = $(btn).find('input').val();
if (goto_id) {
$.ajax({
url: "/" + window.location.pathname.split("/")[1] + "/formset-data-delete/" + goto_id + "/?next=" + window.location.pathname,
error: function () {
console.log("error");
},
success: function (data) {
$(btn).parents('.item').remove();
},
type: 'GET'
});
} else {
$(btn).parents('.item').remove();
}
var forms = $('.item'); // Get all the forms
// Update the total number of forms (1 less than before)
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
var i = 0;
// Go through the forms and set their indices, names and IDs
for (formCount = forms.length; i < formCount; i++) {
$(forms.get(i)).find('.formset-field').each(function () {
updateElementIndex(this, prefix, i);
});
}
} // End if
return false;
}
$("body").on('click', '.remove-form-row', function () {
deleteForm($(this), String($('.add-form-row').attr('id')));
});
$("body").on('click', '.add-form-row', function () {
return addForm($(this), String($(this).attr('id')));
});
我想在我的项目中添加多formSet。我遵循了https://github.com/shitalluitel/formset这个代码。但是,请在我的终端中显示此错误消息:“配置不正确:禁止在未明确定义“字段”或“排除”的情况下调用modelformset_factory。”
答案 0 :(得分:0)
inside views.py更改此行
journalEntryFormset = modelformset_factory( AccountsJournalVoucherEntery, form=AccountsPymtVoucherForm)
对此
journalEntryFormset = modelformset_factory( AccountsJournalVoucherEntery, form=AccountsPymtVoucherForm, fields={'field_1', 'field_2', 'field_....'})