Kaydet (Commit) 9555f2be authored tarafından Jannis Leidel's avatar Jannis Leidel

Fixed #12692 - Properly handle the extra clause of admin inline formsets. Also…

Fixed #12692 - Properly handle the extra clause of admin inline formsets. Also fixes #12703, second error.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12369 bcc190cf-cafb-0310-a4f2-bffc1f526a37
üst f70a0882
......@@ -20,29 +20,24 @@
var updateElementIndex = function(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);
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);
}
};
var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
var initialForms = $("#id_" + options.prefix + "-INITIAL_FORMS");
var maxForms = parseInt(totalForms.val());
var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS");
// only show the add button if we are allowed to add more items
var showAddButton = (maxForms - parseInt(initialForms.val())) > 0;
var showAddButton = ((maxForms.val() == 0) || ((maxForms.val()-totalForms.val()) > 0));
var selectedItems = this;
$(this).each(function(i) {
$(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
// hide the extras, but only if there were no form errors
if (!$(".errornote").html()) {
var relatedItems = $(selectedItems).not("." + options.emptyCssClass);
extraRows = relatedItems.length;
if (parseInt(initialForms.val()) >= 0) {
$(relatedItems).slice(initialForms.val()).remove();
} else {
$(relatedItems).remove();
}
totalForms.val(parseInt(initialForms.val()));
}
});
if ($(this).length && showAddButton) {
var addButton;
......@@ -58,9 +53,8 @@
addButton = $(this).filter(":last").next().find("a");
}
addButton.click(function() {
var totalForms = parseInt($("#id_" + options.prefix + "-TOTAL_FORMS").val());
var initialForms = parseInt($("#id_" + options.prefix + "-INITIAL_FORMS").val());
var nextIndex = totalForms + 1;
var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
var nextIndex = parseInt(totalForms.val()) + 1;
var template = $("#" + options.prefix + "-empty");
var row = template.clone(true).get(0);
$(row).removeClass(options.emptyCssClass).removeAttr("id").insertBefore($(template));
......@@ -79,10 +73,13 @@
// last child element of the form's container:
$(row).children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>");
}
$(row).find("input,select,textarea,label").each(function() {
updateElementIndex(this, options.prefix, totalForms.val());
});
// Update number of total forms
$("#id_" + options.prefix + "-TOTAL_FORMS").val(nextIndex);
// Hide add button in case we've hit the max
if (maxForms <= nextIndex) {
$(totalForms).val(nextIndex);
// Hide add button in case we've hit the max, except we want to add infinitely
if ((maxForms.val() != 0) && (maxForms.val() <= totalForms.val())) {
addButton.parent().hide();
}
// The delete button of each row triggers a bunch of other things
......@@ -91,44 +88,45 @@
var row = $(this).parents("." + options.formCssClass);
row.remove();
// If a post-delete callback was provided, call it with the deleted form:
if (options.removed) options.removed(row);
if (options.removed) {
options.removed(row);
}
// Update the TOTAL_FORMS form count.
var forms = $("." + options.formCssClass);
$("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
// Show add button again once we drop below max
if (maxForms >= forms.length) {
if ((maxForms.val() == 0) || (maxForms.val() >= forms.length)) {
addButton.parent().show();
}
// Also, update names and ids for all remaining form controls
// so they remain in sequence:
for (var i=0, formCount=forms.length; i<formCount; i++) {
for (var i=0, formCount=forms.length; i<formCount; i++)
{
$(forms.get(i)).find("input,select,textarea,label").each(function() {
updateElementIndex(this, options.prefix, i);
});
}
return false;
});
$(row).find("input,select,textarea,label").each(function() {
updateElementIndex(this, options.prefix, totalForms);
});
// If a post-add callback was supplied, call it with the added form:
if (options.added) options.added($(row));
if (options.added) {
options.added($(row));
}
return false;
});
}
return $(this);
return this;
}
/* Setup plugin defaults */
$.fn.formset.defaults = {
prefix: "form", // The form prefix for your django formset
addText: "add another", // Text for the add link
deleteText: "remove", // Text for the delete link
addCssClass: "add-row", // CSS class applied to the add link
deleteCssClass: "delete-row", // CSS class applied to the delete link
emptyCssClass: "empty-row", // CSS class applied to the empty row
formCssClass: "dynamic-form", // CSS class applied to each form in a formset
added: null, // Function called each time a new form is added
removed: null // Function called each time a form is deleted
prefix: "form", // The form prefix for your django formset
addText: "add another", // Text for the add link
deleteText: "remove", // Text for the delete link
addCssClass: "add-row", // CSS class applied to the add link
deleteCssClass: "delete-row", // CSS class applied to the delete link
emptyCssClass: "empty-row", // CSS class applied to the empty row
formCssClass: "dynamic-form", // CSS class applied to each form in a formset
added: null, // Function called each time a new form is added
removed: null // Function called each time a form is deleted
}
})(jQuery)
})(jQuery);
(function(a){a.fn.formset=function(b){var k=a.extend({},a.fn.formset.defaults,b);var j=function(o,p,m){var l=new RegExp("("+p+"-\\d+)");var n=p+"-"+m;if(a(o).attr("for")){a(o).attr("for",a(o).attr("for").replace(l,n))}if(o.id){o.id=o.id.replace(l,n)}if(o.name){o.name=o.name.replace(l,n)}};var f=a("#id_"+k.prefix+"-TOTAL_FORMS");var c=a("#id_"+k.prefix+"-INITIAL_FORMS");var h=parseInt(f.val());var i=(h-parseInt(c.val()))>0;var e=this;a(this).each(function(m){a(this).not("."+k.emptyCssClass).addClass(k.formCssClass);if(!a(".errornote").html()){var l=a(e).not("."+k.emptyCssClass);extraRows=l.length;if(parseInt(c.val())>=0){a(l).slice(c.val()).remove()}else{a(l).remove()}f.val(parseInt(c.val()))}});if(a(this).length&&i){var g;if(a(this).attr("tagName")=="TR"){var d=this.eq(0).children().length;a(this).parent().append('<tr class="'+k.addCssClass+'"><td colspan="'+d+'"><a href="javascript:void(0)">'+k.addText+"</a></tr>");g=a(this).parent().find("tr:last a")}else{a(this).filter(":last").after('<div class="'+k.addCssClass+'"><a href="javascript:void(0)">'+k.addText+"</a></div>");g=a(this).filter(":last").next().find("a")}g.click(function(){var o=parseInt(a("#id_"+k.prefix+"-TOTAL_FORMS").val());var n=parseInt(a("#id_"+k.prefix+"-INITIAL_FORMS").val());var l=o+1;var m=a("#"+k.prefix+"-empty");var p=m.clone(true).get(0);a(p).removeClass(k.emptyCssClass).removeAttr("id").insertBefore(a(m));a(p).html(a(p).html().replace(/__prefix__/g,l));a(p).addClass(k.formCssClass).attr("id",k.prefix+l);if(a(p).is("TR")){a(p).children(":last").append('<div><a class="'+k.deleteCssClass+'" href="javascript:void(0)">'+k.deleteText+"</a></div>")}else{if(a(p).is("UL")||a(p).is("OL")){a(p).append('<li><a class="'+k.deleteCssClass+'" href="javascript:void(0)">'+k.deleteText+"</a></li>")}else{a(p).children(":first").append('<span><a class="'+k.deleteCssClass+'" href="javascript:void(0)">'+k.deleteText+"</a></span>")}}a("#id_"+k.prefix+"-TOTAL_FORMS").val(l);if(h<=l){g.parent().hide()}a(p).find("a."+k.deleteCssClass).click(function(){var t=a(this).parents("."+k.formCssClass);t.remove();if(k.removed){k.removed(t)}var q=a("."+k.formCssClass);a("#id_"+k.prefix+"-TOTAL_FORMS").val(q.length);if(h>=q.length){g.parent().show()}for(var r=0,s=q.length;r<s;r++){a(q.get(r)).find("input,select,textarea,label").each(function(){j(this,k.prefix,r)})}return false});a(p).find("input,select,textarea,label").each(function(){j(this,k.prefix,o)});if(k.added){k.added(a(p))}return false})}return a(this)};a.fn.formset.defaults={prefix:"form",addText:"add another",deleteText:"remove",addCssClass:"add-row",deleteCssClass:"delete-row",emptyCssClass:"empty-row",formCssClass:"dynamic-form",added:null,removed:null}})(jQuery);
\ No newline at end of file
(function(a){a.fn.formset=function(f){var b=a.extend({},a.fn.formset.defaults,f),l=function(d,e,j){var c=new RegExp("("+e+"-\\d+)");e=e+"-"+j;a(d).attr("for")&&a(d).attr("for",a(d).attr("for").replace(c,e));if(d.id)d.id=d.id.replace(c,e);if(d.name)d.name=d.name.replace(c,e)};f=a("#id_"+b.prefix+"-TOTAL_FORMS");a("#id_"+b.prefix+"-INITIAL_FORMS");var h=a("#id_"+b.prefix+"-MAX_NUM_FORMS");f=h.val()==0||h.val()-f.val()>0;a(this).each(function(){a(this).not("."+b.emptyCssClass).addClass(b.formCssClass)});
if(a(this).length&&f){var i;if(a(this).attr("tagName")=="TR"){f=this.eq(0).children().length;a(this).parent().append('<tr class="'+b.addCssClass+'"><td colspan="'+f+'"><a href="javascript:void(0)">'+b.addText+"</a></tr>");i=a(this).parent().find("tr:last a")}else{a(this).filter(":last").after('<div class="'+b.addCssClass+'"><a href="javascript:void(0)">'+b.addText+"</a></div>");i=a(this).filter(":last").next().find("a")}i.click(function(){var d=a("#id_"+b.prefix+"-TOTAL_FORMS"),e=parseInt(d.val())+
1,j=a("#"+b.prefix+"-empty"),c=j.clone(true).get(0);a(c).removeClass(b.emptyCssClass).removeAttr("id").insertBefore(a(j));a(c).html(a(c).html().replace(/__prefix__/g,e));a(c).addClass(b.formCssClass).attr("id",b.prefix+e);if(a(c).is("TR"))a(c).children(":last").append('<div><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></div>");else a(c).is("UL")||a(c).is("OL")?a(c).append('<li><a class="'+b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></li>"):a(c).children(":first").append('<span><a class="'+
b.deleteCssClass+'" href="javascript:void(0)">'+b.deleteText+"</a></span>");a(c).find("input,select,textarea,label").each(function(){l(this,b.prefix,d.val())});a(d).val(e);h.val()!=0&&h.val()<=d.val()&&i.parent().hide();a(c).find("a."+b.deleteCssClass).click(function(){var g=a(this).parents("."+b.formCssClass);g.remove();b.removed&&b.removed(g);g=a("."+b.formCssClass);a("#id_"+b.prefix+"-TOTAL_FORMS").val(g.length);if(h.val()==0||h.val()>=g.length)i.parent().show();for(var k=0,m=g.length;k<m;k++)a(g.get(k)).find("input,select,textarea,label").each(function(){l(this,
b.prefix,k)});return false});b.added&&b.added(a(c));return false})}return this};a.fn.formset.defaults={prefix:"form",addText:"add another",deleteText:"remove",addCssClass:"add-row",deleteCssClass:"delete-row",emptyCssClass:"empty-row",formCssClass:"dynamic-form",added:null,removed:null}})(jQuery);
......@@ -19,24 +19,25 @@
</div>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function($) {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .inline-related";
updateInlineLabel = function(row) {
$(rows).find(".inline_label").each(function(i) {
var count = i + 1;
$(this).html($(this).html().replace(/(#\d+)/g, "#" + count));
(function($) {
$(document).ready(function() {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .inline-related";
updateInlineLabel = function(row) {
$(rows).find(".inline_label").each(function(i) {
var count = i + 1;
$(this).html($(this).html().replace(/(#\d+)/g, "#" + count));
});
}
$(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form",
removed: updateInlineLabel,
added: updateInlineLabel
});
}
$(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form",
removed: updateInlineLabel,
added: updateInlineLabel
});
});
})(jQuery.noConflict());
</script>
\ No newline at end of file
......@@ -65,23 +65,24 @@
</div>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function($) {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .tabular.inline-related tbody tr";
alternatingRows = function(row) {
$(rows).not(".add-row").removeClass("row1 row2")
.filter(":even").addClass("row1").end()
.filter(rows + ":odd").addClass("row2");
}
$(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form",
removed: alternatingRows,
added: alternatingRows
(function($) {
$(document).ready(function($) {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .tabular.inline-related tbody tr";
alternatingRows = function(row) {
$(rows).not(".add-row").removeClass("row1 row2")
.filter(":even").addClass("row1").end()
.filter(rows + ":odd").addClass("row2");
}
$(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form",
removed: alternatingRows,
added: alternatingRows
});
});
});
})(jQuery.noConflict());
</script>
\ No newline at end of file
......@@ -12,6 +12,7 @@ __all__ = ('BaseFormSet', 'all_valid')
# special field names
TOTAL_FORM_COUNT = 'TOTAL_FORMS'
INITIAL_FORM_COUNT = 'INITIAL_FORMS'
MAX_NUM_FORM_COUNT = 'MAX_NUM_FORMS'
ORDERING_FIELD_NAME = 'ORDER'
DELETION_FIELD_NAME = 'DELETE'
......@@ -24,6 +25,7 @@ class ManagementForm(Form):
def __init__(self, *args, **kwargs):
self.base_fields[TOTAL_FORM_COUNT] = IntegerField(widget=HiddenInput)
self.base_fields[INITIAL_FORM_COUNT] = IntegerField(widget=HiddenInput)
self.base_fields[MAX_NUM_FORM_COUNT] = IntegerField(widget=HiddenInput)
super(ManagementForm, self).__init__(*args, **kwargs)
class BaseFormSet(StrAndUnicode):
......@@ -56,7 +58,8 @@ class BaseFormSet(StrAndUnicode):
else:
form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial={
TOTAL_FORM_COUNT: self.total_form_count(),
INITIAL_FORM_COUNT: self.initial_form_count()
INITIAL_FORM_COUNT: self.initial_form_count(),
MAX_NUM_FORM_COUNT: self.max_num
})
return form
management_form = property(_management_form)
......
......@@ -9,6 +9,7 @@ class DeletionTests(TestCase):
data = {
'form-TOTAL_FORMS': u'1',
'form-INITIAL_FORMS': u'1',
'form-MAX_NUM_FORMS': u'0',
'form-0-id': str(poet.pk),
'form-0-name': u'test',
'form-0-DELETE': u'on',
......@@ -27,6 +28,7 @@ class DeletionTests(TestCase):
data = {
'form-TOTAL_FORMS': u'1',
'form-INITIAL_FORMS': u'0',
'form-MAX_NUM_FORMS': u'0',
'form-0-id': u'',
'form-0-name': u'x' * 1000,
}
......@@ -53,6 +55,7 @@ class DeletionTests(TestCase):
data = {
'form-TOTAL_FORMS': u'1',
'form-INITIAL_FORMS': u'1',
'form-MAX_NUM_FORMS': u'0',
'form-0-id': u'1',
'form-0-name': u'x' * 1000,
}
......
......@@ -87,6 +87,7 @@ class AdminViewBasicTest(TestCase):
# inline data
"article_set-TOTAL_FORMS": u"3",
"article_set-INITIAL_FORMS": u"0",
"article_set-MAX_NUM_FORMS": u"0",
}
response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data)
self.failUnlessEqual(response.status_code, 302) # redirect somewhere
......@@ -97,6 +98,7 @@ class AdminViewBasicTest(TestCase):
# inline data
"article_set-TOTAL_FORMS": u"6",
"article_set-INITIAL_FORMS": u"3",
"article_set-MAX_NUM_FORMS": u"0",
"article_set-0-id": u"1",
# there is no title in database, give one here or formset will fail.
"article_set-0-title": u"Norske bostaver æøå skaper problemer",
......@@ -864,6 +866,7 @@ class AdminViewUnicodeTest(TestCase):
# inline data
"chapter_set-TOTAL_FORMS": u"6",
"chapter_set-INITIAL_FORMS": u"3",
"chapter_set-MAX_NUM_FORMS": u"0",
"chapter_set-0-id": u"1",
"chapter_set-0-title": u"Norske bostaver æøå skaper problemer",
"chapter_set-0-content": u"&lt;p&gt;Svært frustrerende med UnicodeDecodeError&lt;/p&gt;",
......@@ -926,14 +929,14 @@ class AdminViewListEditable(TestCase):
def test_changelist_input_html(self):
response = self.client.get('/test_admin/admin/admin_views/person/')
# 2 inputs per object(the field and the hidden id field) = 6
# 2 management hidden fields = 2
# 3 management hidden fields = 3
# 4 action inputs (3 regular checkboxes, 1 checkbox to select all)
# main form submit button = 1
# search field and search submit button = 2
# CSRF field = 1
# field to track 'select all' across paginated views = 1
# 6 + 2 + 4 + 1 + 2 + 1 + 1 = 17 inputs
self.failUnlessEqual(response.content.count("<input"), 17)
# 6 + 3 + 4 + 1 + 2 + 1 + 1 = 18 inputs
self.failUnlessEqual(response.content.count("<input"), 18)
# 1 select per object = 3 selects
self.failUnlessEqual(response.content.count("<select"), 4)
......@@ -941,6 +944,7 @@ class AdminViewListEditable(TestCase):
data = {
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
"form-0-gender": "1",
"form-0-id": "1",
......@@ -961,6 +965,7 @@ class AdminViewListEditable(TestCase):
data = {
"form-TOTAL_FORMS": "2",
"form-INITIAL_FORMS": "2",
"form-MAX_NUM_FORMS": "0",
"form-0-id": "1",
"form-0-gender": "1",
......@@ -978,6 +983,7 @@ class AdminViewListEditable(TestCase):
data = {
"form-TOTAL_FORMS": "1",
"form-INITIAL_FORMS": "1",
"form-MAX_NUM_FORMS": "0",
"form-0-id": "1",
"form-0-gender": "1"
......@@ -998,6 +1004,7 @@ class AdminViewListEditable(TestCase):
data = {
"form-TOTAL_FORMS": "4",
"form-INITIAL_FORMS": "4",
"form-MAX_NUM_FORMS": "0",
"form-0-order": "14",
"form-0-id": "1",
......@@ -1069,9 +1076,11 @@ class AdminInheritedInlinesTest(TestCase):
# inline data
"accounts-TOTAL_FORMS": u"1",
"accounts-INITIAL_FORMS": u"0",
"accounts-MAX_NUM_FORMS": u"0",
"accounts-0-username": foo_user,
"accounts-2-TOTAL_FORMS": u"1",
"accounts-2-INITIAL_FORMS": u"0",
"accounts-2-MAX_NUM_FORMS": u"0",
"accounts-2-0-username": bar_user,
}
......@@ -1096,6 +1105,7 @@ class AdminInheritedInlinesTest(TestCase):
"accounts-TOTAL_FORMS": "2",
"accounts-INITIAL_FORMS": u"1",
"accounts-MAX_NUM_FORMS": u"0",
"accounts-0-username": "%s-1" % foo_user,
"accounts-0-account_ptr": "1",
......@@ -1103,6 +1113,7 @@ class AdminInheritedInlinesTest(TestCase):
"accounts-2-TOTAL_FORMS": u"2",
"accounts-2-INITIAL_FORMS": u"1",
"accounts-2-MAX_NUM_FORMS": u"0",
"accounts-2-0-username": "%s-1" % bar_user,
"accounts-2-0-account_ptr": "2",
......@@ -1348,6 +1359,7 @@ class AdminInlineFileUploadTest(TestCase):
"name": u"Test Gallery",
"pictures-TOTAL_FORMS": u"2",
"pictures-INITIAL_FORMS": u"1",
"pictures-MAX_NUM_FORMS": u"0",
"pictures-0-id": u"1",
"pictures-0-gallery": u"1",
"pictures-0-name": "Test Picture",
......@@ -1370,6 +1382,7 @@ class AdminInlineTests(TestCase):
"widget_set-TOTAL_FORMS": "3",
"widget_set-INITIAL_FORMS": u"0",
"widget_set-MAX_NUM_FORMS": u"0",
"widget_set-0-id": "",
"widget_set-0-owner": "1",
"widget_set-0-name": "",
......@@ -1382,6 +1395,7 @@ class AdminInlineTests(TestCase):
"doohickey_set-TOTAL_FORMS": "3",
"doohickey_set-INITIAL_FORMS": u"0",
"doohickey_set-MAX_NUM_FORMS": u"0",
"doohickey_set-0-owner": "1",
"doohickey_set-0-code": "",
"doohickey_set-0-name": "",
......@@ -1394,6 +1408,7 @@ class AdminInlineTests(TestCase):
"grommet_set-TOTAL_FORMS": "3",
"grommet_set-INITIAL_FORMS": u"0",
"grommet_set-MAX_NUM_FORMS": u"0",
"grommet_set-0-code": "",
"grommet_set-0-owner": "1",
"grommet_set-0-name": "",
......@@ -1406,6 +1421,7 @@ class AdminInlineTests(TestCase):
"whatsit_set-TOTAL_FORMS": "3",
"whatsit_set-INITIAL_FORMS": u"0",
"whatsit_set-MAX_NUM_FORMS": u"0",
"whatsit_set-0-owner": "1",
"whatsit_set-0-index": "",
"whatsit_set-0-name": "",
......@@ -1418,6 +1434,7 @@ class AdminInlineTests(TestCase):
"fancydoodad_set-TOTAL_FORMS": "3",
"fancydoodad_set-INITIAL_FORMS": u"0",
"fancydoodad_set-MAX_NUM_FORMS": u"0",
"fancydoodad_set-0-doodad_ptr": "",
"fancydoodad_set-0-owner": "1",
"fancydoodad_set-0-name": "",
......@@ -1433,6 +1450,7 @@ class AdminInlineTests(TestCase):
"category_set-TOTAL_FORMS": "3",
"category_set-INITIAL_FORMS": "0",
"category_set-MAX_NUM_FORMS": "0",
"category_set-0-order": "",
"category_set-0-id": "",
"category_set-0-collector": "1",
......@@ -1624,6 +1642,7 @@ class AdminInlineTests(TestCase):
"category_set-TOTAL_FORMS": "7",
"category_set-INITIAL_FORMS": "4",
"category_set-MAX_NUM_FORMS": "0",
"category_set-0-order": "14",
"category_set-0-id": "1",
......@@ -1750,9 +1769,9 @@ class ReadonlyTest(TestCase):
response = self.client.get('/test_admin/admin/admin_views/post/add/')
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'name="posted"')
# 3 fields + 2 submit buttons + 2 inline management form fields, + 2
# hidden fields for inlines + 1 field for the inline
self.assertEqual(response.content.count("input"), 10)
# 3 fields + 2 submit buttons + 4 inline management form fields, + 2
# hidden fields for inlines + 1 field for the inline + 2 empty form
self.assertEqual(response.content.count("input"), 14)
self.assertContains(response, formats.localize(datetime.date.today()))
self.assertContains(response,
"<label>Awesomeness level:</label>")
......@@ -1773,6 +1792,7 @@ class ReadonlyTest(TestCase):
"content": "This is an incredible development.",
"link_set-TOTAL_FORMS": "1",
"link_set-INITIAL_FORMS": "0",
"link_set-MAX_NUM_FORMS": "0",
}
response = self.client.post('/test_admin/admin/admin_views/post/add/', data)
self.assertEqual(response.status_code, 302)
......
......@@ -20,7 +20,7 @@ but we'll look at how to do so later.
>>> formset = ChoiceFormSet(auto_id=False, prefix='choices')
>>> print formset
<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" />
<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" />
<tr><th>Choice:</th><td><input type="text" name="choices-0-choice" /></td></tr>
<tr><th>Votes:</th><td><input type="text" name="choices-0-votes" /></td></tr>
......@@ -34,6 +34,7 @@ the TOTAL_FORMS field appropriately.
>>> data = {
... 'choices-TOTAL_FORMS': '1', # the number of forms rendered
... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... }
......@@ -60,6 +61,7 @@ any of the forms.
>>> data = {
... 'choices-TOTAL_FORMS': '1', # the number of forms rendered
... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '',
... }
......@@ -90,6 +92,7 @@ Let's simulate what would happen if we submitted this form.
>>> data = {
... 'choices-TOTAL_FORMS': '2', # the number of forms rendered
... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-1-choice': '',
......@@ -111,6 +114,7 @@ handle that later.
>>> data = {
... 'choices-TOTAL_FORMS': '2', # the number of forms rendered
... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-1-choice': 'The Decemberists',
......@@ -130,6 +134,7 @@ handle that case later.
>>> data = {
... 'choices-TOTAL_FORMS': '2', # the number of forms rendered
... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': '', # deleted value
... 'choices-0-votes': '', # deleted value
... 'choices-1-choice': '',
......@@ -167,6 +172,7 @@ number of forms to be completed.
>>> data = {
... 'choices-TOTAL_FORMS': '3', # the number of forms rendered
... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': '',
... 'choices-0-votes': '',
... 'choices-1-choice': '',
......@@ -187,6 +193,7 @@ We can just fill out one of the forms.
>>> data = {
... 'choices-TOTAL_FORMS': '3', # the number of forms rendered
... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-1-choice': '',
......@@ -207,6 +214,7 @@ And once again, if we try to partially complete a form, validation will fail.
>>> data = {
... 'choices-TOTAL_FORMS': '3', # the number of forms rendered
... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-1-choice': 'The Decemberists',
......@@ -274,6 +282,7 @@ To delete something, we just need to set that form's special delete field to
>>> data = {
... 'choices-TOTAL_FORMS': '3', # the number of forms rendered
... 'choices-INITIAL_FORMS': '2', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-0-DELETE': '',
......@@ -303,6 +312,7 @@ it's going to be deleted.
>>> data = {
... 'check-TOTAL_FORMS': '3', # the number of forms rendered
... 'check-INITIAL_FORMS': '2', # the number of forms with initial data
... 'check-MAX_NUM_FORMS': '0', # max number of forms
... 'check-0-field': '200',
... 'check-0-DELETE': '',
... 'check-1-field': '50',
......@@ -351,6 +361,7 @@ something at the front of the list, you'd need to set it's order to 0.
>>> data = {
... 'choices-TOTAL_FORMS': '3', # the number of forms rendered
... 'choices-INITIAL_FORMS': '2', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-0-ORDER': '1',
......@@ -377,6 +388,7 @@ they will be sorted below everything else.
>>> data = {
... 'choices-TOTAL_FORMS': '4', # the number of forms rendered
... 'choices-INITIAL_FORMS': '3', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-0-ORDER': '1',
......@@ -406,6 +418,7 @@ Ordering should work with blank fieldsets.
>>> data = {
... 'choices-TOTAL_FORMS': '3', # the number of forms rendered
... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... }
>>> formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
......@@ -450,6 +463,7 @@ Let's delete Fergie, and put The Decemberists ahead of Calexico.
>>> data = {
... 'choices-TOTAL_FORMS': '4', # the number of forms rendered
... 'choices-INITIAL_FORMS': '3', # the number of forms with initial data
... 'choices-MAX_NUM_FORMS': '0', # max number of forms
... 'choices-0-choice': 'Calexico',
... 'choices-0-votes': '100',
... 'choices-0-ORDER': '1',
......@@ -508,6 +522,7 @@ We start out with a some duplicate data.
>>> data = {
... 'drinks-TOTAL_FORMS': '2', # the number of forms rendered
... 'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
... 'drinks-MAX_NUM_FORMS': '0', # max number of forms
... 'drinks-0-name': 'Gin and Tonic',
... 'drinks-1-name': 'Gin and Tonic',
... }
......@@ -529,6 +544,7 @@ Make sure we didn't break the valid case.
>>> data = {
... 'drinks-TOTAL_FORMS': '2', # the number of forms rendered
... 'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
... 'drinks-MAX_NUM_FORMS': '0', # max number of forms
... 'drinks-0-name': 'Gin and Tonic',
... 'drinks-1-name': 'Bloody Mary',
... }
......
......@@ -58,6 +58,7 @@ class GenericAdminViewTest(TestCase):
# inline data
"generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"1",
"generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"0",
"generic_inline_admin-media-content_type-object_id-MAX_NUM_FORMS": u"0",
}
response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data)
self.failUnlessEqual(response.status_code, 302) # redirect somewhere
......@@ -71,6 +72,7 @@ class GenericAdminViewTest(TestCase):
# inline data
"generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"3",
"generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"2",
"generic_inline_admin-media-content_type-object_id-MAX_NUM_FORMS": u"0",
"generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.mp3_media_pk,
"generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3",
"generic_inline_admin-media-content_type-object_id-1-id": u"%d" % self.png_media_pk,
......@@ -192,6 +194,7 @@ class GenericInlineAdminWithUniqueTogetherTest(TestCase):
# inline data
"generic_inline_admin-phonenumber-content_type-object_id-TOTAL_FORMS": u"1",
"generic_inline_admin-phonenumber-content_type-object_id-INITIAL_FORMS": u"0",
"generic_inline_admin-phonenumber-content_type-object_id-MAX_NUM_FORMS": u"0",
"generic_inline_admin-phonenumber-content_type-object_id-0-id": "",
"generic_inline_admin-phonenumber-content_type-object_id-0-phone_number": "555-555-5555",
}
......
......@@ -10,6 +10,7 @@ class DeletionTests(TestCase):
data = {
'poem_set-TOTAL_FORMS': u'1',
'poem_set-INITIAL_FORMS': u'1',
'poem_set-MAX_NUM_FORMS': u'0',
'poem_set-0-id': str(poem.pk),
'poem_set-0-poet': str(poet.pk),
'poem_set-0-name': u'test',
......@@ -30,6 +31,7 @@ class DeletionTests(TestCase):
data = {
'poem_set-TOTAL_FORMS': u'1',
'poem_set-INITIAL_FORMS': u'0',
'poem_set-MAX_NUM_FORMS': u'0',
'poem_set-0-id': u'',
'poem_set-0-poem': u'1',
'poem_set-0-name': u'x' * 1000,
......@@ -58,6 +60,7 @@ class DeletionTests(TestCase):
data = {
'poem_set-TOTAL_FORMS': u'1',
'poem_set-INITIAL_FORMS': u'1',
'poem_set-MAX_NUM_FORMS': u'0',
'poem_set-0-id': u'1',
'poem_set-0-poem': u'1',
'poem_set-0-name': u'x' * 1000,
......@@ -88,6 +91,7 @@ class DeletionTests(TestCase):
data = {
'child_set-TOTAL_FORMS': u'1',
'child_set-INITIAL_FORMS': u'0',
'child_set-MAX_NUM_FORMS': u'0',
'child_set-0-name': u'child',
}
formset = ChildFormSet(data, instance=school)
......
......@@ -20,6 +20,7 @@ class InlineFormsetTests(TestCase):
'username': u'apollo13',
'usersite_set-TOTAL_FORMS': u'1',
'usersite_set-INITIAL_FORMS': u'0',
'usersite_set-MAX_NUM_FORMS': u'0',
'usersite_set-0-data': u'10',
'usersite_set-0-user': u'apollo13'
}
......@@ -43,6 +44,7 @@ class InlineFormsetTests(TestCase):
data = {
'usersite_set-TOTAL_FORMS': u'1',
'usersite_set-INITIAL_FORMS': u'1',
'usersite_set-MAX_NUM_FORMS': u'0',
'usersite_set-0-id': unicode(usersite[0]['id']),
'usersite_set-0-data': u'11',
'usersite_set-0-user': u'apollo13'
......@@ -60,6 +62,7 @@ class InlineFormsetTests(TestCase):
data = {
'usersite_set-TOTAL_FORMS': u'2',
'usersite_set-INITIAL_FORMS': u'1',
'usersite_set-MAX_NUM_FORMS': u'0',
'usersite_set-0-id': unicode(usersite[0]['id']),
'usersite_set-0-data': u'11',
'usersite_set-0-user': u'apollo13',
......@@ -92,6 +95,7 @@ class InlineFormsetTests(TestCase):
'name': u"Guido's House of Pasta",
'manager_set-TOTAL_FORMS': u'1',
'manager_set-INITIAL_FORMS': u'0',
'manager_set-MAX_NUM_FORMS': u'0',
'manager_set-0-name': u'Guido Van Rossum'
}
restaurant = User()
......@@ -113,6 +117,7 @@ class InlineFormsetTests(TestCase):
data = {
'manager_set-TOTAL_FORMS': u'1',
'manager_set-INITIAL_FORMS': u'1',
'manager_set-MAX_NUM_FORMS': u'0',
'manager_set-0-id': unicode(manager[0]['id']),
'manager_set-0-name': u'Terry Gilliam'
}
......@@ -128,6 +133,7 @@ class InlineFormsetTests(TestCase):
data = {
'manager_set-TOTAL_FORMS': u'2',
'manager_set-INITIAL_FORMS': u'1',
'manager_set-MAX_NUM_FORMS': u'0',
'manager_set-0-id': unicode(manager[0]['id']),
'manager_set-0-name': u'Terry Gilliam',
'manager_set-1-name': u'John Cleese'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment