Ticket #12692: 12692.3.diff
File 12692.3.diff, 47.5 KB (added by , 15 years ago) |
---|
-
django/contrib/admin/media/js/inlines.js
diff --git a/django/contrib/admin/media/js/inlines.js b/django/contrib/admin/media/js/inlines.js index c45ce58..4532815 100644
a b 20 20 var updateElementIndex = function(el, prefix, ndx) { 21 21 var id_regex = new RegExp("(" + prefix + "-\\d+)"); 22 22 var replacement = prefix + "-" + ndx; 23 if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement)); 24 if (el.id) el.id = el.id.replace(id_regex, replacement); 25 if (el.name) el.name = el.name.replace(id_regex, replacement); 23 if ($(el).attr("for")) { 24 $(el).attr("for", $(el).attr("for").replace(id_regex, replacement)); 25 } 26 if (el.id) { 27 el.id = el.id.replace(id_regex, replacement); 28 } 29 if (el.name) { 30 el.name = el.name.replace(id_regex, replacement); 31 } 26 32 }; 27 33 var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS"); 28 34 var initialForms = $("#id_" + options.prefix + "-INITIAL_FORMS"); 29 var maxForms = parseInt(totalForms.val());35 var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS"); 30 36 // only show the add button if we are allowed to add more items 31 var showAddButton = ( maxForms - parseInt(initialForms.val())) > 0;37 var showAddButton = ((maxForms.val() == 0) || ((maxForms.val()-totalForms.val()) > 0)); 32 38 var selectedItems = this; 33 39 $(this).each(function(i) { 34 40 $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); 35 // hide the extras, but only if there were no form errors36 if (!$(".errornote").html()) {37 var relatedItems = $(selectedItems).not("." + options.emptyCssClass);38 extraRows = relatedItems.length;39 if (parseInt(initialForms.val()) >= 0) {40 $(relatedItems).slice(initialForms.val()).remove();41 } else {42 $(relatedItems).remove();43 }44 totalForms.val(parseInt(initialForms.val()));45 }46 41 }); 47 42 if ($(this).length && showAddButton) { 48 43 var addButton; … … 58 53 addButton = $(this).filter(":last").next().find("a"); 59 54 } 60 55 addButton.click(function() { 61 var totalForms = parseInt($("#id_" + options.prefix + "-TOTAL_FORMS").val()); 62 var initialForms = parseInt($("#id_" + options.prefix + "-INITIAL_FORMS").val()); 63 var nextIndex = totalForms + 1; 56 var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS"); 57 var nextIndex = parseInt(totalForms.val()) + 1; 64 58 var template = $("#" + options.prefix + "-empty"); 65 59 var row = template.clone(true).get(0); 66 60 $(row).removeClass(options.emptyCssClass).removeAttr("id").insertBefore($(template)); … … 79 73 // last child element of the form's container: 80 74 $(row).children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>"); 81 75 } 76 $(row).find("input,select,textarea,label").each(function() { 77 updateElementIndex(this, options.prefix, totalForms.val()); 78 }); 82 79 // Update number of total forms 83 $( "#id_" + options.prefix + "-TOTAL_FORMS").val(nextIndex);84 // Hide add button in case we've hit the max 85 if ( maxForms <= nextIndex) {80 $(totalForms).val(nextIndex); 81 // Hide add button in case we've hit the max, except we want to add infinitely 82 if ((maxForms.val() != 0) && (maxForms.val() <= totalForms.val())) { 86 83 addButton.parent().hide(); 87 84 } 88 85 // The delete button of each row triggers a bunch of other things … … 91 88 var row = $(this).parents("." + options.formCssClass); 92 89 row.remove(); 93 90 // If a post-delete callback was provided, call it with the deleted form: 94 if (options.removed) options.removed(row); 91 if (options.removed) { 92 options.removed(row); 93 } 95 94 // Update the TOTAL_FORMS form count. 96 95 var forms = $("." + options.formCssClass); 97 96 $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); 98 97 // Show add button again once we drop below max 99 if ( maxForms >= forms.length) {98 if ((maxForms.val() == 0) || (maxForms.val() >= forms.length)) { 100 99 addButton.parent().show(); 101 100 } 102 101 // Also, update names and ids for all remaining form controls 103 102 // so they remain in sequence: 104 for (var i=0, formCount=forms.length; i<formCount; i++) { 103 for (var i=0, formCount=forms.length; i<formCount; i++) 104 { 105 105 $(forms.get(i)).find("input,select,textarea,label").each(function() { 106 106 updateElementIndex(this, options.prefix, i); 107 107 }); 108 108 } 109 109 return false; 110 110 }); 111 $(row).find("input,select,textarea,label").each(function() {112 updateElementIndex(this, options.prefix, totalForms);113 });114 111 // If a post-add callback was supplied, call it with the added form: 115 if (options.added) options.added($(row)); 112 if (options.added) { 113 options.added($(row)); 114 } 116 115 return false; 117 116 }); 118 117 } 119 118 return $(this); 120 119 } 121 122 120 /* Setup plugin defaults */ 123 121 $.fn.formset.defaults = { 124 prefix: "form", 125 addText: "add another", 126 deleteText: "remove", 127 addCssClass: "add-row", 128 deleteCssClass: "delete-row", 129 emptyCssClass: "empty-row", 130 formCssClass: "dynamic-form", 131 added: null, 132 removed: null 122 prefix: "form", // The form prefix for your django formset 123 addText: "add another", // Text for the add link 124 deleteText: "remove", // Text for the delete link 125 addCssClass: "add-row", // CSS class applied to the add link 126 deleteCssClass: "delete-row", // CSS class applied to the delete link 127 emptyCssClass: "empty-row", // CSS class applied to the empty row 128 formCssClass: "dynamic-form", // CSS class applied to each form in a formset 129 added: null, // Function called each time a new form is added 130 removed: null // Function called each time a form is deleted 133 131 } 134 132 })(jQuery) -
django/contrib/admin/media/js/inlines.min.js
diff --git a/django/contrib/admin/media/js/inlines.min.js b/django/contrib/admin/media/js/inlines.min.js index a17907d..93a59af 100644
a b 1 (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); 2 No newline at end of file 1 (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)}); 2 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())+ 3 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="'+ 4 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, 5 b.prefix,k)});return false});b.added&&b.added(a(c));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); -
django/forms/formsets.py
diff --git a/django/forms/formsets.py b/django/forms/formsets.py index a86c18f..58af0ac 100644
a b __all__ = ('BaseFormSet', 'all_valid') 12 12 # special field names 13 13 TOTAL_FORM_COUNT = 'TOTAL_FORMS' 14 14 INITIAL_FORM_COUNT = 'INITIAL_FORMS' 15 MAX_NUM_FORM_COUNT = 'MAX_NUM_FORMS' 15 16 ORDERING_FIELD_NAME = 'ORDER' 16 17 DELETION_FIELD_NAME = 'DELETE' 17 18 … … class ManagementForm(Form): 24 25 def __init__(self, *args, **kwargs): 25 26 self.base_fields[TOTAL_FORM_COUNT] = IntegerField(widget=HiddenInput) 26 27 self.base_fields[INITIAL_FORM_COUNT] = IntegerField(widget=HiddenInput) 28 self.base_fields[MAX_NUM_FORM_COUNT] = IntegerField(widget=HiddenInput) 27 29 super(ManagementForm, self).__init__(*args, **kwargs) 28 30 29 31 class BaseFormSet(StrAndUnicode): … … class BaseFormSet(StrAndUnicode): 56 58 else: 57 59 form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial={ 58 60 TOTAL_FORM_COUNT: self.total_form_count(), 59 INITIAL_FORM_COUNT: self.initial_form_count() 61 INITIAL_FORM_COUNT: self.initial_form_count(), 62 MAX_NUM_FORM_COUNT: self.max_num 60 63 }) 61 64 return form 62 65 management_form = property(_management_form) -
tests/modeltests/model_formsets/models.py
diff --git a/tests/modeltests/model_formsets/models.py b/tests/modeltests/model_formsets/models.py index 702523e..e8c3e98 100644
a b __test__ = {'API_TESTS': """ 200 200 >>> data = { 201 201 ... 'form-TOTAL_FORMS': '3', # the number of forms rendered 202 202 ... 'form-INITIAL_FORMS': '0', # the number of forms with initial data 203 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 203 204 ... 'form-0-name': 'Charles Baudelaire', 204 205 ... 'form-1-name': 'Arthur Rimbaud', 205 206 ... 'form-2-name': '', … … them in alphabetical order by name. 237 238 >>> data = { 238 239 ... 'form-TOTAL_FORMS': '3', # the number of forms rendered 239 240 ... 'form-INITIAL_FORMS': '2', # the number of forms with initial data 241 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 240 242 ... 'form-0-id': '2', 241 243 ... 'form-0-name': 'Arthur Rimbaud', 242 244 ... 'form-1-id': '1', … … deltetion, make sure we don't save that form. 280 282 >>> data = { 281 283 ... 'form-TOTAL_FORMS': '4', # the number of forms rendered 282 284 ... 'form-INITIAL_FORMS': '3', # the number of forms with initial data 285 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 283 286 ... 'form-0-id': '2', 284 287 ... 'form-0-name': 'Arthur Rimbaud', 285 288 ... 'form-1-id': '1', … … Let's edit a record to ensure save only returns that one record. 309 312 >>> data = { 310 313 ... 'form-TOTAL_FORMS': '4', # the number of forms rendered 311 314 ... 'form-INITIAL_FORMS': '3', # the number of forms with initial data 315 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 312 316 ... 'form-0-id': '2', 313 317 ... 'form-0-name': 'Walt Whitman', 314 318 ... 'form-1-id': '1', … … Test the behavior of commit=False and save_m2m 339 343 >>> data = { 340 344 ... 'form-TOTAL_FORMS': '2', # the number of forms rendered 341 345 ... 'form-INITIAL_FORMS': '1', # the number of forms with initial data 346 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 342 347 ... 'form-0-id': '1', 343 348 ... 'form-0-name': '2nd Tuesday of the Week Meeting', 344 349 ... 'form-0-authors': [2, 1, 3, 4], … … used. 393 398 >>> data = { 394 399 ... 'form-TOTAL_FORMS': '3', # the number of forms rendered 395 400 ... 'form-INITIAL_FORMS': '0', # the number of forms with initial data 401 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 396 402 ... 'form-0-name': 'Walt Whitman', 397 403 ... 'form-1-name': 'Charles Baudelaire', 398 404 ... 'form-2-name': '', … … True 419 425 >>> data = { 420 426 ... 'form-TOTAL_FORMS': '1', # the number of forms rendered 421 427 ... 'form-INITIAL_FORMS': '0', # the number of forms with initial data 428 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 422 429 ... 'form-0-author_ptr': '', 423 430 ... 'form-0-name': 'Ernest Hemingway', 424 431 ... 'form-0-write_speed': '10', … … True 442 449 >>> data = { 443 450 ... 'form-TOTAL_FORMS': '2', # the number of forms rendered 444 451 ... 'form-INITIAL_FORMS': '1', # the number of forms with initial data 452 ... 'form-MAX_NUM_FORMS': '0', # the max number of forms 445 453 ... 'form-0-author_ptr': hemingway_id, 446 454 ... 'form-0-name': 'Ernest Hemingway', 447 455 ... 'form-0-write_speed': '10', … … admin system's edit inline functionality works. 476 484 >>> data = { 477 485 ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered 478 486 ... 'book_set-INITIAL_FORMS': '0', # the number of forms with initial data 487 ... 'book_set-MAX_NUM_FORMS': '0', # the max number of forms 479 488 ... 'book_set-0-title': 'Les Fleurs du Mal', 480 489 ... 'book_set-1-title': '', 481 490 ... 'book_set-2-title': '', … … book. 510 519 >>> data = { 511 520 ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered 512 521 ... 'book_set-INITIAL_FORMS': '1', # the number of forms with initial data 522 ... 'book_set-MAX_NUM_FORMS': '0', # the max number of forms 513 523 ... 'book_set-0-id': '1', 514 524 ... 'book_set-0-title': 'Les Fleurs du Mal', 515 525 ... 'book_set-1-title': 'Les Paradis Artificiels', … … This is used in the admin for save_as functionality. 536 546 >>> data = { 537 547 ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered 538 548 ... 'book_set-INITIAL_FORMS': '2', # the number of forms with initial data 549 ... 'book_set-MAX_NUM_FORMS': '0', # the max number of forms 539 550 ... 'book_set-0-id': '1', 540 551 ... 'book_set-0-title': 'Les Fleurs du Mal', 541 552 ... 'book_set-1-id': '2', … … Test inline formsets where the inline-edited object has a custom primary key tha 573 584 >>> data = { 574 585 ... 'bookwithcustompk_set-TOTAL_FORMS': '1', # the number of forms rendered 575 586 ... 'bookwithcustompk_set-INITIAL_FORMS': '0', # the number of forms with initial data 587 ... 'bookwithcustompk_set-MAX_NUM_FORMS': '0', # the max number of forms 576 588 ... 'bookwithcustompk_set-0-my_pk': '77777', 577 589 ... 'bookwithcustompk_set-0-title': 'Les Fleurs du Mal', 578 590 ... } … … has a non AutoField yet auto-created primary key. 603 615 >>> data = { 604 616 ... 'alternatebook_set-TOTAL_FORMS': '1', # the number of forms rendered 605 617 ... 'alternatebook_set-INITIAL_FORMS': '0', # the number of forms with initial data 618 ... 'alternatebook_set-MAX_NUM_FORMS': '0', # the max number of forms 606 619 ... 'alternatebook_set-0-title': 'Flowers of Evil', 607 620 ... 'alternatebook_set-0-notes': 'English translation of Les Fleurs du Mal' 608 621 ... } … … True 631 644 >>> data = { 632 645 ... 'poem_set-TOTAL_FORMS': '3', # the number of forms rendered 633 646 ... 'poem_set-INITIAL_FORMS': '0', # the number of forms with initial data 647 ... 'poem_set-MAX_NUM_FORMS': '0', # the max number of forms 634 648 ... 'poem_set-0-name': 'The Cloud in Trousers', 635 649 ... 'poem_set-1-name': 'I', 636 650 ... 'poem_set-2-name': '', … … We can provide a custom queryset to our InlineFormSet: 659 673 >>> data = { 660 674 ... 'book_set-TOTAL_FORMS': '5', # the number of forms rendered 661 675 ... 'book_set-INITIAL_FORMS': '3', # the number of forms with initial data 676 ... 'book_set-MAX_NUM_FORMS': '0', # the max number of forms 662 677 ... 'book_set-0-id': '1', 663 678 ... 'book_set-0-title': 'Les Fleurs du Mal', 664 679 ... 'book_set-1-id': '2', … … True 682 697 >>> data = { 683 698 ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered 684 699 ... 'book_set-INITIAL_FORMS': '1', # the number of forms with initial data 700 ... 'book_set-MAX_NUM_FORMS': '0', # the max number of forms 685 701 ... 'book_set-0-id': '5', 686 702 ... 'book_set-0-title': 'Flowers of Evil', 687 703 ... 'book_set-1-title': 'Revue des deux mondes', … … We need to ensure that it is displayed 718 734 >>> data = { 719 735 ... 'owner_set-TOTAL_FORMS': '2', 720 736 ... 'owner_set-INITIAL_FORMS': '0', 737 ... 'owner_set-MAX_NUM_FORMS': '0', 721 738 ... 'owner_set-0-auto_id': '', 722 739 ... 'owner_set-0-name': u'Joe Perry', 723 740 ... 'owner_set-1-auto_id': '', … … True 739 756 >>> data = { 740 757 ... 'owner_set-TOTAL_FORMS': '3', 741 758 ... 'owner_set-INITIAL_FORMS': '1', 759 ... 'owner_set-MAX_NUM_FORMS': '0', 742 760 ... 'owner_set-0-auto_id': u'1', 743 761 ... 'owner_set-0-name': u'Joe Perry', 744 762 ... 'owner_set-1-auto_id': '', … … True 767 785 768 786 >>> owner = Owner.objects.get(name=u'Joe Perry') 769 787 >>> FormSet = inlineformset_factory(Owner, OwnerProfile, max_num=1, can_delete=False) 770 788 >>> FormSet.max_num 789 1 771 790 >>> formset = FormSet(instance=owner) 772 791 >>> for form in formset.forms: 773 792 ... print form.as_p() … … True 776 795 >>> data = { 777 796 ... 'ownerprofile-TOTAL_FORMS': '1', 778 797 ... 'ownerprofile-INITIAL_FORMS': '0', 798 ... 'ownerprofile-MAX_NUM_FORMS': '1', 779 799 ... 'ownerprofile-0-owner': '', 780 800 ... 'ownerprofile-0-age': u'54', 781 801 ... } … … True 784 804 True 785 805 >>> formset.save() 786 806 [<OwnerProfile: Joe Perry is 54>] 787 788 807 >>> formset = FormSet(instance=owner) 789 808 >>> for form in formset.forms: 790 809 ... print form.as_p() … … True 793 812 >>> data = { 794 813 ... 'ownerprofile-TOTAL_FORMS': '1', 795 814 ... 'ownerprofile-INITIAL_FORMS': '1', 815 ... 'ownerprofile-MAX_NUM_FORMS': '1', 796 816 ... 'ownerprofile-0-owner': u'1', 797 817 ... 'ownerprofile-0-age': u'55', 798 818 ... } … … True 805 825 # ForeignKey with unique=True should enforce max_num=1 806 826 807 827 >>> FormSet = inlineformset_factory(Place, Location, can_delete=False) 828 >>> FormSet.max_num 829 1 808 830 >>> formset = FormSet(instance=place) 809 831 >>> for form in formset.forms: 810 832 ... print form.as_p() … … True 826 848 >>> data = { 827 849 ... 'form-TOTAL_FORMS': '1', 828 850 ... 'form-INITIAL_FORMS': '0', 851 ... 'form-MAX_NUM_FORMS': '0', 829 852 ... 'form-0-slug': 'car-red', 830 853 ... } 831 854 >>> formset = FormSet(data) … … True 837 860 >>> data = { 838 861 ... 'form-TOTAL_FORMS': '1', 839 862 ... 'form-INITIAL_FORMS': '0', 863 ... 'form-MAX_NUM_FORMS': '0', 840 864 ... 'form-0-slug': 'car-red', 841 865 ... } 842 866 >>> formset = FormSet(data) … … False 851 875 >>> data = { 852 876 ... 'form-TOTAL_FORMS': '1', 853 877 ... 'form-INITIAL_FORMS': '0', 878 ... 'form-MAX_NUM_FORMS': '0', 854 879 ... 'form-0-price': u'12.00', 855 880 ... 'form-0-quantity': '1', 856 881 ... } … … True 863 888 >>> data = { 864 889 ... 'form-TOTAL_FORMS': '1', 865 890 ... 'form-INITIAL_FORMS': '0', 891 ... 'form-MAX_NUM_FORMS': '0', 866 892 ... 'form-0-price': u'12.00', 867 893 ... 'form-0-quantity': '1', 868 894 ... } … … False 880 906 >>> data = { 881 907 ... 'revision_set-TOTAL_FORMS': '1', 882 908 ... 'revision_set-INITIAL_FORMS': '0', 909 ... 'revision_set-MAX_NUM_FORMS': '0', 883 910 ... 'revision_set-0-repository': repository.pk, 884 911 ... 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76', 885 912 ... 'revision_set-0-DELETE': '', … … True 894 921 >>> data = { 895 922 ... 'revision_set-TOTAL_FORMS': '1', 896 923 ... 'revision_set-INITIAL_FORMS': '0', 924 ... 'revision_set-MAX_NUM_FORMS': '0', 897 925 ... 'revision_set-0-repository': repository.pk, 898 926 ... 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76', 899 927 ... 'revision_set-0-DELETE': '', … … False 911 939 >>> data = { 912 940 ... 'revision_set-TOTAL_FORMS': '1', 913 941 ... 'revision_set-INITIAL_FORMS': '0', 942 ... 'revision_set-MAX_NUM_FORMS': '0', 914 943 ... 'revision_set-0-repository': repository.pk, 915 944 ... 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76', 916 945 ... 'revision_set-0-DELETE': '', … … False 940 969 >>> data = { 941 970 ... 'membership_set-TOTAL_FORMS': '1', 942 971 ... 'membership_set-INITIAL_FORMS': '0', 972 ... 'membership_set-MAX_NUM_FORMS': '0', 943 973 ... 'membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), 944 974 ... 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), 945 975 ... 'membership_set-0-karma': '', … … True 954 984 >>> filled_data = { 955 985 ... 'membership_set-TOTAL_FORMS': '1', 956 986 ... 'membership_set-INITIAL_FORMS': '0', 987 ... 'membership_set-MAX_NUM_FORMS': '0', 957 988 ... 'membership_set-0-date_joined': unicode(one_day_later.strftime('%Y-%m-%d %H:%M:%S')), 958 989 ... 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), 959 990 ... 'membership_set-0-karma': '', … … False 976 1007 >>> data = { 977 1008 ... 'membership_set-TOTAL_FORMS': '1', 978 1009 ... 'membership_set-INITIAL_FORMS': '0', 1010 ... 'membership_set-MAX_NUM_FORMS': '0', 979 1011 ... 'membership_set-0-date_joined_0': unicode(now.strftime('%Y-%m-%d')), 980 1012 ... 'membership_set-0-date_joined_1': unicode(now.strftime('%H:%M:%S')), 981 1013 ... 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), … … True 1011 1043 >>> data = { 1012 1044 ... 'form-TOTAL_FORMS': 2, 1013 1045 ... 'form-INITIAL_FORMS': 0, 1046 ... 'form-MAX_NUM_FORMS': '0', 1014 1047 ... 'form-0-slug': 'red_car', 1015 1048 ... 'form-1-slug': 'red_car', 1016 1049 ... } … … False 1024 1057 >>> data = { 1025 1058 ... 'form-TOTAL_FORMS': 2, 1026 1059 ... 'form-INITIAL_FORMS': 0, 1060 ... 'form-MAX_NUM_FORMS': '0', 1027 1061 ... 'form-0-price': '25', 1028 1062 ... 'form-0-quantity': '7', 1029 1063 ... 'form-1-price': '25', … … False 1041 1075 >>> data = { 1042 1076 ... 'form-TOTAL_FORMS': '2', 1043 1077 ... 'form-INITIAL_FORMS': '0', 1078 ... 'form-MAX_NUM_FORMS': '0', 1044 1079 ... 'form-0-price': '24', 1045 1080 ... 'form-1-price': '24', 1046 1081 ... } … … True 1054 1089 >>> data = { 1055 1090 ... 'book_set-TOTAL_FORMS': '2', 1056 1091 ... 'book_set-INITIAL_FORMS': '2', 1092 ... 'book_set-MAX_NUM_FORMS': '0', 1057 1093 ... 1058 1094 ... 'book_set-0-title': 'The 2008 Election', 1059 1095 ... 'book_set-0-author': str(author.id), … … False 1075 1111 >>> data = { 1076 1112 ... 'form-TOTAL_FORMS': '2', 1077 1113 ... 'form-INITIAL_FORMS': '0', 1114 ... 'form-MAX_NUM_FORMS': '0', 1078 1115 ... 1079 1116 ... 'form-0-title': 'blah', 1080 1117 ... 'form-0-slug': 'Morning', … … False 1096 1133 >>> data = { 1097 1134 ... 'form-TOTAL_FORMS': '2', 1098 1135 ... 'form-INITIAL_FORMS': '0', 1136 ... 'form-MAX_NUM_FORMS': '0', 1099 1137 ... 1100 1138 ... 'form-0-title': 'foo', 1101 1139 ... 'form-0-slug': 'Morning in Prague', … … False 1115 1153 >>> data = { 1116 1154 ... 'form-TOTAL_FORMS': '2', 1117 1155 ... 'form-INITIAL_FORMS': '0', 1156 ... 'form-MAX_NUM_FORMS': '0', 1118 1157 ... 1119 1158 ... 'form-0-title': 'foo', 1120 1159 ... 'form-0-slug': 'Morning in Prague', -
tests/modeltests/model_formsets/tests.py
diff --git a/tests/modeltests/model_formsets/tests.py b/tests/modeltests/model_formsets/tests.py index d343fc7..62489ba 100644
a b class DeletionTests(TestCase): 9 9 data = { 10 10 'form-TOTAL_FORMS': u'1', 11 11 'form-INITIAL_FORMS': u'1', 12 'form-MAX_NUM_FORMS': u'0', 12 13 'form-0-id': str(poet.pk), 13 14 'form-0-name': u'test', 14 15 'form-0-DELETE': u'on', … … class DeletionTests(TestCase): 27 28 data = { 28 29 'form-TOTAL_FORMS': u'1', 29 30 'form-INITIAL_FORMS': u'0', 31 'form-MAX_NUM_FORMS': u'0', 30 32 'form-0-id': u'', 31 33 'form-0-name': u'x' * 1000, 32 34 } … … class DeletionTests(TestCase): 53 55 data = { 54 56 'form-TOTAL_FORMS': u'1', 55 57 'form-INITIAL_FORMS': u'1', 58 'form-MAX_NUM_FORMS': u'0', 56 59 'form-0-id': u'1', 57 60 'form-0-name': u'x' * 1000, 58 61 } -
tests/regressiontests/admin_views/tests.py
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index 7fc52b3..d52a57f 100644
a b class AdminViewBasicTest(TestCase): 87 87 # inline data 88 88 "article_set-TOTAL_FORMS": u"3", 89 89 "article_set-INITIAL_FORMS": u"0", 90 "article_set-MAX_NUM_FORMS": u"0", 90 91 } 91 92 response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data) 92 93 self.failUnlessEqual(response.status_code, 302) # redirect somewhere … … class AdminViewBasicTest(TestCase): 97 98 # inline data 98 99 "article_set-TOTAL_FORMS": u"6", 99 100 "article_set-INITIAL_FORMS": u"3", 101 "article_set-MAX_NUM_FORMS": u"0", 100 102 "article_set-0-id": u"1", 101 103 # there is no title in database, give one here or formset will fail. 102 104 "article_set-0-title": u"Norske bostaver æøå skaper problemer", … … class AdminViewUnicodeTest(TestCase): 864 866 # inline data 865 867 "chapter_set-TOTAL_FORMS": u"6", 866 868 "chapter_set-INITIAL_FORMS": u"3", 869 "chapter_set-MAX_NUM_FORMS": u"0", 867 870 "chapter_set-0-id": u"1", 868 871 "chapter_set-0-title": u"Norske bostaver æøå skaper problemer", 869 872 "chapter_set-0-content": u"<p>Svært frustrerende med UnicodeDecodeError</p>", … … class AdminViewListEditable(TestCase): 926 929 def test_changelist_input_html(self): 927 930 response = self.client.get('/test_admin/admin/admin_views/person/') 928 931 # 2 inputs per object(the field and the hidden id field) = 6 929 # 2 management hidden fields = 2932 # 3 management hidden fields = 3 930 933 # 4 action inputs (3 regular checkboxes, 1 checkbox to select all) 931 934 # main form submit button = 1 932 935 # search field and search submit button = 2 933 936 # CSRF field = 1 934 937 # field to track 'select all' across paginated views = 1 935 # 6 + 2 + 4 + 1 + 2 + 1 + 1 = 17inputs936 self.failUnlessEqual(response.content.count("<input"), 1 7)938 # 6 + 3 + 4 + 1 + 2 + 1 + 1 = 18 inputs 939 self.failUnlessEqual(response.content.count("<input"), 18) 937 940 # 1 select per object = 3 selects 938 941 self.failUnlessEqual(response.content.count("<select"), 4) 939 942 … … class AdminViewListEditable(TestCase): 941 944 data = { 942 945 "form-TOTAL_FORMS": "3", 943 946 "form-INITIAL_FORMS": "3", 947 "form-MAX_NUM_FORMS": "0", 944 948 945 949 "form-0-gender": "1", 946 950 "form-0-id": "1", … … class AdminViewListEditable(TestCase): 961 965 data = { 962 966 "form-TOTAL_FORMS": "2", 963 967 "form-INITIAL_FORMS": "2", 968 "form-MAX_NUM_FORMS": "0", 964 969 965 970 "form-0-id": "1", 966 971 "form-0-gender": "1", … … class AdminViewListEditable(TestCase): 978 983 data = { 979 984 "form-TOTAL_FORMS": "1", 980 985 "form-INITIAL_FORMS": "1", 986 "form-MAX_NUM_FORMS": "0", 981 987 982 988 "form-0-id": "1", 983 989 "form-0-gender": "1" … … class AdminViewListEditable(TestCase): 998 1004 data = { 999 1005 "form-TOTAL_FORMS": "4", 1000 1006 "form-INITIAL_FORMS": "4", 1007 "form-MAX_NUM_FORMS": "0", 1001 1008 1002 1009 "form-0-order": "14", 1003 1010 "form-0-id": "1", … … class AdminInheritedInlinesTest(TestCase): 1069 1076 # inline data 1070 1077 "accounts-TOTAL_FORMS": u"1", 1071 1078 "accounts-INITIAL_FORMS": u"0", 1079 "accounts-MAX_NUM_FORMS": u"0", 1072 1080 "accounts-0-username": foo_user, 1073 1081 "accounts-2-TOTAL_FORMS": u"1", 1074 1082 "accounts-2-INITIAL_FORMS": u"0", 1083 "accounts-2-MAX_NUM_FORMS": u"0", 1075 1084 "accounts-2-0-username": bar_user, 1076 1085 } 1077 1086 … … class AdminInheritedInlinesTest(TestCase): 1096 1105 1097 1106 "accounts-TOTAL_FORMS": "2", 1098 1107 "accounts-INITIAL_FORMS": u"1", 1108 "accounts-MAX_NUM_FORMS": u"0", 1099 1109 1100 1110 "accounts-0-username": "%s-1" % foo_user, 1101 1111 "accounts-0-account_ptr": "1", … … class AdminInheritedInlinesTest(TestCase): 1103 1113 1104 1114 "accounts-2-TOTAL_FORMS": u"2", 1105 1115 "accounts-2-INITIAL_FORMS": u"1", 1116 "accounts-2-MAX_NUM_FORMS": u"0", 1106 1117 1107 1118 "accounts-2-0-username": "%s-1" % bar_user, 1108 1119 "accounts-2-0-account_ptr": "2", … … class AdminInlineFileUploadTest(TestCase): 1348 1359 "name": u"Test Gallery", 1349 1360 "pictures-TOTAL_FORMS": u"2", 1350 1361 "pictures-INITIAL_FORMS": u"1", 1362 "pictures-MAX_NUM_FORMS": u"0", 1351 1363 "pictures-0-id": u"1", 1352 1364 "pictures-0-gallery": u"1", 1353 1365 "pictures-0-name": "Test Picture", … … class AdminInlineTests(TestCase): 1370 1382 1371 1383 "widget_set-TOTAL_FORMS": "3", 1372 1384 "widget_set-INITIAL_FORMS": u"0", 1385 "widget_set-MAX_NUM_FORMS": u"0", 1373 1386 "widget_set-0-id": "", 1374 1387 "widget_set-0-owner": "1", 1375 1388 "widget_set-0-name": "", … … class AdminInlineTests(TestCase): 1382 1395 1383 1396 "doohickey_set-TOTAL_FORMS": "3", 1384 1397 "doohickey_set-INITIAL_FORMS": u"0", 1398 "doohickey_set-MAX_NUM_FORMS": u"0", 1385 1399 "doohickey_set-0-owner": "1", 1386 1400 "doohickey_set-0-code": "", 1387 1401 "doohickey_set-0-name": "", … … class AdminInlineTests(TestCase): 1394 1408 1395 1409 "grommet_set-TOTAL_FORMS": "3", 1396 1410 "grommet_set-INITIAL_FORMS": u"0", 1411 "grommet_set-MAX_NUM_FORMS": u"0", 1397 1412 "grommet_set-0-code": "", 1398 1413 "grommet_set-0-owner": "1", 1399 1414 "grommet_set-0-name": "", … … class AdminInlineTests(TestCase): 1406 1421 1407 1422 "whatsit_set-TOTAL_FORMS": "3", 1408 1423 "whatsit_set-INITIAL_FORMS": u"0", 1424 "whatsit_set-MAX_NUM_FORMS": u"0", 1409 1425 "whatsit_set-0-owner": "1", 1410 1426 "whatsit_set-0-index": "", 1411 1427 "whatsit_set-0-name": "", … … class AdminInlineTests(TestCase): 1418 1434 1419 1435 "fancydoodad_set-TOTAL_FORMS": "3", 1420 1436 "fancydoodad_set-INITIAL_FORMS": u"0", 1437 "fancydoodad_set-MAX_NUM_FORMS": u"0", 1421 1438 "fancydoodad_set-0-doodad_ptr": "", 1422 1439 "fancydoodad_set-0-owner": "1", 1423 1440 "fancydoodad_set-0-name": "", … … class AdminInlineTests(TestCase): 1433 1450 1434 1451 "category_set-TOTAL_FORMS": "3", 1435 1452 "category_set-INITIAL_FORMS": "0", 1453 "category_set-MAX_NUM_FORMS": "0", 1436 1454 "category_set-0-order": "", 1437 1455 "category_set-0-id": "", 1438 1456 "category_set-0-collector": "1", … … class AdminInlineTests(TestCase): 1624 1642 1625 1643 "category_set-TOTAL_FORMS": "7", 1626 1644 "category_set-INITIAL_FORMS": "4", 1645 "category_set-MAX_NUM_FORMS": "0", 1627 1646 1628 1647 "category_set-0-order": "14", 1629 1648 "category_set-0-id": "1", … … class ReadonlyTest(TestCase): 1750 1769 response = self.client.get('/test_admin/admin/admin_views/post/add/') 1751 1770 self.assertEqual(response.status_code, 200) 1752 1771 self.assertNotContains(response, 'name="posted"') 1753 # 3 fields + 2 submit buttons + 2inline management form fields, + 21754 # hidden fields for inlines + 1 field for the inline 1755 self.assertEqual(response.content.count("input"), 1 0)1772 # 3 fields + 2 submit buttons + 4 inline management form fields, + 2 1773 # hidden fields for inlines + 1 field for the inline + 2 empty form 1774 self.assertEqual(response.content.count("input"), 14) 1756 1775 self.assertContains(response, formats.localize(datetime.date.today())) 1757 1776 self.assertContains(response, 1758 1777 "<label>Awesomeness level:</label>") … … class ReadonlyTest(TestCase): 1773 1792 "content": "This is an incredible development.", 1774 1793 "link_set-TOTAL_FORMS": "1", 1775 1794 "link_set-INITIAL_FORMS": "0", 1795 "link_set-MAX_NUM_FORMS": "0", 1776 1796 } 1777 1797 response = self.client.post('/test_admin/admin/admin_views/post/add/', data) 1778 1798 self.assertEqual(response.status_code, 302) -
tests/regressiontests/forms/formsets.py
diff --git a/tests/regressiontests/forms/formsets.py b/tests/regressiontests/forms/formsets.py index 7999710..700ab7c 100644
a b but we'll look at how to do so later. 20 20 21 21 >>> formset = ChoiceFormSet(auto_id=False, prefix='choices') 22 22 >>> print formset 23 <input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /> 23 <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" /> 24 24 <tr><th>Choice:</th><td><input type="text" name="choices-0-choice" /></td></tr> 25 25 <tr><th>Votes:</th><td><input type="text" name="choices-0-votes" /></td></tr> 26 26 … … the TOTAL_FORMS field appropriately. 34 34 >>> data = { 35 35 ... 'choices-TOTAL_FORMS': '1', # the number of forms rendered 36 36 ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data 37 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 37 38 ... 'choices-0-choice': 'Calexico', 38 39 ... 'choices-0-votes': '100', 39 40 ... } … … any of the forms. 60 61 >>> data = { 61 62 ... 'choices-TOTAL_FORMS': '1', # the number of forms rendered 62 63 ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data 64 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 63 65 ... 'choices-0-choice': 'Calexico', 64 66 ... 'choices-0-votes': '', 65 67 ... } … … Let's simulate what would happen if we submitted this form. 90 92 >>> data = { 91 93 ... 'choices-TOTAL_FORMS': '2', # the number of forms rendered 92 94 ... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data 95 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 93 96 ... 'choices-0-choice': 'Calexico', 94 97 ... 'choices-0-votes': '100', 95 98 ... 'choices-1-choice': '', … … handle that later. 111 114 >>> data = { 112 115 ... 'choices-TOTAL_FORMS': '2', # the number of forms rendered 113 116 ... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data 117 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 114 118 ... 'choices-0-choice': 'Calexico', 115 119 ... 'choices-0-votes': '100', 116 120 ... 'choices-1-choice': 'The Decemberists', … … handle that case later. 130 134 >>> data = { 131 135 ... 'choices-TOTAL_FORMS': '2', # the number of forms rendered 132 136 ... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data 137 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 133 138 ... 'choices-0-choice': '', # deleted value 134 139 ... 'choices-0-votes': '', # deleted value 135 140 ... 'choices-1-choice': '', … … number of forms to be completed. 167 172 >>> data = { 168 173 ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered 169 174 ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data 175 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 170 176 ... 'choices-0-choice': '', 171 177 ... 'choices-0-votes': '', 172 178 ... 'choices-1-choice': '', … … We can just fill out one of the forms. 187 193 >>> data = { 188 194 ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered 189 195 ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data 196 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 190 197 ... 'choices-0-choice': 'Calexico', 191 198 ... 'choices-0-votes': '100', 192 199 ... 'choices-1-choice': '', … … And once again, if we try to partially complete a form, validation will fail. 207 214 >>> data = { 208 215 ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered 209 216 ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data 217 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 210 218 ... 'choices-0-choice': 'Calexico', 211 219 ... 'choices-0-votes': '100', 212 220 ... 'choices-1-choice': 'The Decemberists', … … To delete something, we just need to set that form's special delete field to 274 282 >>> data = { 275 283 ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered 276 284 ... 'choices-INITIAL_FORMS': '2', # the number of forms with initial data 285 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 277 286 ... 'choices-0-choice': 'Calexico', 278 287 ... 'choices-0-votes': '100', 279 288 ... 'choices-0-DELETE': '', … … it's going to be deleted. 303 312 >>> data = { 304 313 ... 'check-TOTAL_FORMS': '3', # the number of forms rendered 305 314 ... 'check-INITIAL_FORMS': '2', # the number of forms with initial data 315 ... 'check-MAX_NUM_FORMS': '0', # max number of forms 306 316 ... 'check-0-field': '200', 307 317 ... 'check-0-DELETE': '', 308 318 ... 'check-1-field': '50', … … something at the front of the list, you'd need to set it's order to 0. 351 361 >>> data = { 352 362 ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered 353 363 ... 'choices-INITIAL_FORMS': '2', # the number of forms with initial data 364 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 354 365 ... 'choices-0-choice': 'Calexico', 355 366 ... 'choices-0-votes': '100', 356 367 ... 'choices-0-ORDER': '1', … … they will be sorted below everything else. 377 388 >>> data = { 378 389 ... 'choices-TOTAL_FORMS': '4', # the number of forms rendered 379 390 ... 'choices-INITIAL_FORMS': '3', # the number of forms with initial data 391 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 380 392 ... 'choices-0-choice': 'Calexico', 381 393 ... 'choices-0-votes': '100', 382 394 ... 'choices-0-ORDER': '1', … … Ordering should work with blank fieldsets. 406 418 >>> data = { 407 419 ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered 408 420 ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data 421 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 409 422 ... } 410 423 411 424 >>> formset = ChoiceFormSet(data, auto_id=False, prefix='choices') … … Let's delete Fergie, and put The Decemberists ahead of Calexico. 450 463 >>> data = { 451 464 ... 'choices-TOTAL_FORMS': '4', # the number of forms rendered 452 465 ... 'choices-INITIAL_FORMS': '3', # the number of forms with initial data 466 ... 'choices-MAX_NUM_FORMS': '0', # max number of forms 453 467 ... 'choices-0-choice': 'Calexico', 454 468 ... 'choices-0-votes': '100', 455 469 ... 'choices-0-ORDER': '1', … … We start out with a some duplicate data. 508 522 >>> data = { 509 523 ... 'drinks-TOTAL_FORMS': '2', # the number of forms rendered 510 524 ... 'drinks-INITIAL_FORMS': '0', # the number of forms with initial data 525 ... 'drinks-MAX_NUM_FORMS': '0', # max number of forms 511 526 ... 'drinks-0-name': 'Gin and Tonic', 512 527 ... 'drinks-1-name': 'Gin and Tonic', 513 528 ... } … … Make sure we didn't break the valid case. 529 544 >>> data = { 530 545 ... 'drinks-TOTAL_FORMS': '2', # the number of forms rendered 531 546 ... 'drinks-INITIAL_FORMS': '0', # the number of forms with initial data 547 ... 'drinks-MAX_NUM_FORMS': '0', # max number of forms 532 548 ... 'drinks-0-name': 'Gin and Tonic', 533 549 ... 'drinks-1-name': 'Bloody Mary', 534 550 ... } -
tests/regressiontests/generic_inline_admin/tests.py
diff --git a/tests/regressiontests/generic_inline_admin/tests.py b/tests/regressiontests/generic_inline_admin/tests.py index 21704cd..6853a89 100644
a b class GenericAdminViewTest(TestCase): 58 58 # inline data 59 59 "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"1", 60 60 "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"0", 61 "generic_inline_admin-media-content_type-object_id-MAX_NUM_FORMS": u"0", 61 62 } 62 63 response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data) 63 64 self.failUnlessEqual(response.status_code, 302) # redirect somewhere … … class GenericAdminViewTest(TestCase): 71 72 # inline data 72 73 "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"3", 73 74 "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"2", 75 "generic_inline_admin-media-content_type-object_id-MAX_NUM_FORMS": u"0", 74 76 "generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.mp3_media_pk, 75 77 "generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3", 76 78 "generic_inline_admin-media-content_type-object_id-1-id": u"%d" % self.png_media_pk, … … class GenericInlineAdminWithUniqueTogetherTest(TestCase): 192 194 # inline data 193 195 "generic_inline_admin-phonenumber-content_type-object_id-TOTAL_FORMS": u"1", 194 196 "generic_inline_admin-phonenumber-content_type-object_id-INITIAL_FORMS": u"0", 197 "generic_inline_admin-phonenumber-content_type-object_id-MAX_NUM_FORMS": u"0", 195 198 "generic_inline_admin-phonenumber-content_type-object_id-0-id": "", 196 199 "generic_inline_admin-phonenumber-content_type-object_id-0-phone_number": "555-555-5555", 197 200 } -
tests/regressiontests/inline_formsets/tests.py
diff --git a/tests/regressiontests/inline_formsets/tests.py b/tests/regressiontests/inline_formsets/tests.py index aef6b3f..83d2fba 100644
a b class DeletionTests(TestCase): 10 10 data = { 11 11 'poem_set-TOTAL_FORMS': u'1', 12 12 'poem_set-INITIAL_FORMS': u'1', 13 'poem_set-MAX_NUM_FORMS': u'0', 13 14 'poem_set-0-id': str(poem.pk), 14 15 'poem_set-0-poet': str(poet.pk), 15 16 'poem_set-0-name': u'test', … … class DeletionTests(TestCase): 30 31 data = { 31 32 'poem_set-TOTAL_FORMS': u'1', 32 33 'poem_set-INITIAL_FORMS': u'0', 34 'poem_set-MAX_NUM_FORMS': u'0', 33 35 'poem_set-0-id': u'', 34 36 'poem_set-0-poem': u'1', 35 37 'poem_set-0-name': u'x' * 1000, … … class DeletionTests(TestCase): 58 60 data = { 59 61 'poem_set-TOTAL_FORMS': u'1', 60 62 'poem_set-INITIAL_FORMS': u'1', 63 'poem_set-MAX_NUM_FORMS': u'0', 61 64 'poem_set-0-id': u'1', 62 65 'poem_set-0-poem': u'1', 63 66 'poem_set-0-name': u'x' * 1000, … … class DeletionTests(TestCase): 88 91 data = { 89 92 'child_set-TOTAL_FORMS': u'1', 90 93 'child_set-INITIAL_FORMS': u'0', 94 'child_set-MAX_NUM_FORMS': u'0', 91 95 'child_set-0-name': u'child', 92 96 } 93 97 formset = ChildFormSet(data, instance=school) -
tests/regressiontests/model_formsets_regress/tests.py
diff --git a/tests/regressiontests/model_formsets_regress/tests.py b/tests/regressiontests/model_formsets_regress/tests.py index 4dba9fc..61bc514 100644
a b class InlineFormsetTests(TestCase): 20 20 'username': u'apollo13', 21 21 'usersite_set-TOTAL_FORMS': u'1', 22 22 'usersite_set-INITIAL_FORMS': u'0', 23 'usersite_set-MAX_NUM_FORMS': u'0', 23 24 'usersite_set-0-data': u'10', 24 25 'usersite_set-0-user': u'apollo13' 25 26 } … … class InlineFormsetTests(TestCase): 43 44 data = { 44 45 'usersite_set-TOTAL_FORMS': u'1', 45 46 'usersite_set-INITIAL_FORMS': u'1', 47 'usersite_set-MAX_NUM_FORMS': u'0', 46 48 'usersite_set-0-id': unicode(usersite[0]['id']), 47 49 'usersite_set-0-data': u'11', 48 50 'usersite_set-0-user': u'apollo13' … … class InlineFormsetTests(TestCase): 60 62 data = { 61 63 'usersite_set-TOTAL_FORMS': u'2', 62 64 'usersite_set-INITIAL_FORMS': u'1', 65 'usersite_set-MAX_NUM_FORMS': u'0', 63 66 'usersite_set-0-id': unicode(usersite[0]['id']), 64 67 'usersite_set-0-data': u'11', 65 68 'usersite_set-0-user': u'apollo13', … … class InlineFormsetTests(TestCase): 92 95 'name': u"Guido's House of Pasta", 93 96 'manager_set-TOTAL_FORMS': u'1', 94 97 'manager_set-INITIAL_FORMS': u'0', 98 'manager_set-MAX_NUM_FORMS': u'0', 95 99 'manager_set-0-name': u'Guido Van Rossum' 96 100 } 97 101 restaurant = User() … … class InlineFormsetTests(TestCase): 113 117 data = { 114 118 'manager_set-TOTAL_FORMS': u'1', 115 119 'manager_set-INITIAL_FORMS': u'1', 120 'manager_set-MAX_NUM_FORMS': u'0', 116 121 'manager_set-0-id': unicode(manager[0]['id']), 117 122 'manager_set-0-name': u'Terry Gilliam' 118 123 } … … class InlineFormsetTests(TestCase): 128 133 data = { 129 134 'manager_set-TOTAL_FORMS': u'2', 130 135 'manager_set-INITIAL_FORMS': u'1', 136 'manager_set-MAX_NUM_FORMS': u'0', 131 137 'manager_set-0-id': unicode(manager[0]['id']), 132 138 'manager_set-0-name': u'Terry Gilliam', 133 139 'manager_set-1-name': u'John Cleese'