Ticket #12692: 12692.3.diff

File 12692.3.diff, 47.5 KB (added by Jannis Leidel, 9 years ago)

Patch with Closure compiled min file and modified tests.

  • 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  
    2020                var updateElementIndex = function(el, prefix, ndx) {
    2121                        var id_regex = new RegExp("(" + prefix + "-\\d+)");
    2222                        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                        }
    2632                };
    2733                var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
    2834                var initialForms = $("#id_" + options.prefix + "-INITIAL_FORMS");
    29                 var maxForms = parseInt(totalForms.val());
     35                var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS");
    3036                // 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));
    3238                var selectedItems = this;
    3339                $(this).each(function(i) {
    3440                        $(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
    35                         // hide the extras, but only if there were no form errors
    36                         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                         }
    4641                });
    4742                if ($(this).length && showAddButton) {
    4843                        var addButton;
     
    5853                                addButton = $(this).filter(":last").next().find("a");
    5954                        }
    6055                        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;
    6458                                var template = $("#" + options.prefix + "-empty");
    6559                                var row = template.clone(true).get(0);
    6660                                $(row).removeClass(options.emptyCssClass).removeAttr("id").insertBefore($(template));
     
    7973                                        // last child element of the form's container:
    8074                                        $(row).children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>");
    8175                                }
     76                                $(row).find("input,select,textarea,label").each(function() {
     77                                        updateElementIndex(this, options.prefix, totalForms.val());
     78                                });
    8279                                // 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())) {
    8683                                        addButton.parent().hide();
    8784                                }
    8885                                // The delete button of each row triggers a bunch of other things
     
    9188                                        var row = $(this).parents("." + options.formCssClass);
    9289                                        row.remove();
    9390                                        // 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                                        }
    9594                                        // Update the TOTAL_FORMS form count.
    9695                                        var forms = $("." + options.formCssClass);
    9796                                        $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
    9897                                        // Show add button again once we drop below max
    99                                         if (maxForms >= forms.length) {
     98                                        if ((maxForms.val() == 0) || (maxForms.val() >= forms.length)) {
    10099                                                addButton.parent().show();
    101100                                        }
    102101                                        // Also, update names and ids for all remaining form controls
    103102                                        // 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                                        {
    105105                                                $(forms.get(i)).find("input,select,textarea,label").each(function() {
    106106                                                        updateElementIndex(this, options.prefix, i);
    107107                                                });
    108108                                        }
    109109                                        return false;
    110110                                });
    111                                 $(row).find("input,select,textarea,label").each(function() {
    112                                         updateElementIndex(this, options.prefix, totalForms);
    113                                 });
    114111                                // 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                                }
    116115                                return false;
    117116                        });
    118117                }
    119118                return $(this);
    120119        }
    121 
    122120        /* Setup plugin defaults */
    123121        $.fn.formset.defaults = {
    124                 prefix: "form",                                  // The form prefix for your django formset
    125                 addText: "add another",                  // Text for the add link
    126                 deleteText: "remove",                    // Text for the delete link
    127                 addCssClass: "add-row",                  // CSS class applied to the add link
    128                 deleteCssClass: "delete-row",    // CSS class applied to the delete link
    129                 emptyCssClass: "empty-row",              // CSS class applied to the empty row
    130                 formCssClass: "dynamic-form",    // CSS class applied to each form in a formset
    131                 added: null,                                     // Function called each time a new form is added
    132                 removed: null                                    // Function called each time a form is deleted
     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
    133131        }
    134132})(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)});
     2if(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())+
     31,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="'+
     4b.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,
     5b.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') 
    1212# special field names
    1313TOTAL_FORM_COUNT = 'TOTAL_FORMS'
    1414INITIAL_FORM_COUNT = 'INITIAL_FORMS'
     15MAX_NUM_FORM_COUNT = 'MAX_NUM_FORMS'
    1516ORDERING_FIELD_NAME = 'ORDER'
    1617DELETION_FIELD_NAME = 'DELETE'
    1718
    class ManagementForm(Form): 
    2425    def __init__(self, *args, **kwargs):
    2526        self.base_fields[TOTAL_FORM_COUNT] = IntegerField(widget=HiddenInput)
    2627        self.base_fields[INITIAL_FORM_COUNT] = IntegerField(widget=HiddenInput)
     28        self.base_fields[MAX_NUM_FORM_COUNT] = IntegerField(widget=HiddenInput)
    2729        super(ManagementForm, self).__init__(*args, **kwargs)
    2830
    2931class BaseFormSet(StrAndUnicode):
    class BaseFormSet(StrAndUnicode): 
    5658        else:
    5759            form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial={
    5860                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
    6063            })
    6164        return form
    6265    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': """ 
    200200>>> data = {
    201201...     'form-TOTAL_FORMS': '3', # the number of forms rendered
    202202...     'form-INITIAL_FORMS': '0', # the number of forms with initial data
     203...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    203204...     'form-0-name': 'Charles Baudelaire',
    204205...     'form-1-name': 'Arthur Rimbaud',
    205206...     'form-2-name': '',
    them in alphabetical order by name. 
    237238>>> data = {
    238239...     'form-TOTAL_FORMS': '3', # the number of forms rendered
    239240...     'form-INITIAL_FORMS': '2', # the number of forms with initial data
     241...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    240242...     'form-0-id': '2',
    241243...     'form-0-name': 'Arthur Rimbaud',
    242244...     'form-1-id': '1',
    deltetion, make sure we don't save that form. 
    280282>>> data = {
    281283...     'form-TOTAL_FORMS': '4', # the number of forms rendered
    282284...     'form-INITIAL_FORMS': '3', # the number of forms with initial data
     285...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    283286...     'form-0-id': '2',
    284287...     'form-0-name': 'Arthur Rimbaud',
    285288...     'form-1-id': '1',
    Let's edit a record to ensure save only returns that one record. 
    309312>>> data = {
    310313...     'form-TOTAL_FORMS': '4', # the number of forms rendered
    311314...     'form-INITIAL_FORMS': '3', # the number of forms with initial data
     315...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    312316...     'form-0-id': '2',
    313317...     'form-0-name': 'Walt Whitman',
    314318...     'form-1-id': '1',
    Test the behavior of commit=False and save_m2m 
    339343>>> data = {
    340344...     'form-TOTAL_FORMS': '2', # the number of forms rendered
    341345...     'form-INITIAL_FORMS': '1', # the number of forms with initial data
     346...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    342347...     'form-0-id': '1',
    343348...     'form-0-name': '2nd Tuesday of the Week Meeting',
    344349...     'form-0-authors': [2, 1, 3, 4],
    used. 
    393398>>> data = {
    394399...     'form-TOTAL_FORMS': '3', # the number of forms rendered
    395400...     'form-INITIAL_FORMS': '0', # the number of forms with initial data
     401...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    396402...     'form-0-name': 'Walt Whitman',
    397403...     'form-1-name': 'Charles Baudelaire',
    398404...     'form-2-name': '',
    True 
    419425>>> data = {
    420426...     'form-TOTAL_FORMS': '1', # the number of forms rendered
    421427...     'form-INITIAL_FORMS': '0', # the number of forms with initial data
     428...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    422429...     'form-0-author_ptr': '',
    423430...     'form-0-name': 'Ernest Hemingway',
    424431...     'form-0-write_speed': '10',
    True 
    442449>>> data = {
    443450...     'form-TOTAL_FORMS': '2', # the number of forms rendered
    444451...     'form-INITIAL_FORMS': '1', # the number of forms with initial data
     452...     'form-MAX_NUM_FORMS': '0', # the max number of forms
    445453...     'form-0-author_ptr': hemingway_id,
    446454...     'form-0-name': 'Ernest Hemingway',
    447455...     'form-0-write_speed': '10',
    admin system's edit inline functionality works. 
    476484>>> data = {
    477485...     'book_set-TOTAL_FORMS': '3', # the number of forms rendered
    478486...     'book_set-INITIAL_FORMS': '0', # the number of forms with initial data
     487...     'book_set-MAX_NUM_FORMS': '0', # the max number of forms
    479488...     'book_set-0-title': 'Les Fleurs du Mal',
    480489...     'book_set-1-title': '',
    481490...     'book_set-2-title': '',
    book. 
    510519>>> data = {
    511520...     'book_set-TOTAL_FORMS': '3', # the number of forms rendered
    512521...     'book_set-INITIAL_FORMS': '1', # the number of forms with initial data
     522...     'book_set-MAX_NUM_FORMS': '0', # the max number of forms
    513523...     'book_set-0-id': '1',
    514524...     'book_set-0-title': 'Les Fleurs du Mal',
    515525...     'book_set-1-title': 'Les Paradis Artificiels',
    This is used in the admin for save_as functionality. 
    536546>>> data = {
    537547...     'book_set-TOTAL_FORMS': '3', # the number of forms rendered
    538548...     'book_set-INITIAL_FORMS': '2', # the number of forms with initial data
     549...     'book_set-MAX_NUM_FORMS': '0', # the max number of forms
    539550...     'book_set-0-id': '1',
    540551...     'book_set-0-title': 'Les Fleurs du Mal',
    541552...     'book_set-1-id': '2',
    Test inline formsets where the inline-edited object has a custom primary key tha 
    573584>>> data = {
    574585...     'bookwithcustompk_set-TOTAL_FORMS': '1', # the number of forms rendered
    575586...     'bookwithcustompk_set-INITIAL_FORMS': '0', # the number of forms with initial data
     587...     'bookwithcustompk_set-MAX_NUM_FORMS': '0', # the max number of forms
    576588...     'bookwithcustompk_set-0-my_pk': '77777',
    577589...     'bookwithcustompk_set-0-title': 'Les Fleurs du Mal',
    578590... }
    has a non AutoField yet auto-created primary key. 
    603615>>> data = {
    604616...     'alternatebook_set-TOTAL_FORMS': '1', # the number of forms rendered
    605617...     'alternatebook_set-INITIAL_FORMS': '0', # the number of forms with initial data
     618...     'alternatebook_set-MAX_NUM_FORMS': '0', # the max number of forms
    606619...     'alternatebook_set-0-title': 'Flowers of Evil',
    607620...     'alternatebook_set-0-notes': 'English translation of Les Fleurs du Mal'
    608621... }
    True 
    631644>>> data = {
    632645...     'poem_set-TOTAL_FORMS': '3', # the number of forms rendered
    633646...     'poem_set-INITIAL_FORMS': '0', # the number of forms with initial data
     647...     'poem_set-MAX_NUM_FORMS': '0', # the max number of forms
    634648...     'poem_set-0-name': 'The Cloud in Trousers',
    635649...     'poem_set-1-name': 'I',
    636650...     'poem_set-2-name': '',
    We can provide a custom queryset to our InlineFormSet: 
    659673>>> data = {
    660674...     'book_set-TOTAL_FORMS': '5', # the number of forms rendered
    661675...     'book_set-INITIAL_FORMS': '3', # the number of forms with initial data
     676...     'book_set-MAX_NUM_FORMS': '0', # the max number of forms
    662677...     'book_set-0-id': '1',
    663678...     'book_set-0-title': 'Les Fleurs du Mal',
    664679...     'book_set-1-id': '2',
    True 
    682697>>> data = {
    683698...     'book_set-TOTAL_FORMS': '3', # the number of forms rendered
    684699...     'book_set-INITIAL_FORMS': '1', # the number of forms with initial data
     700...     'book_set-MAX_NUM_FORMS': '0', # the max number of forms
    685701...     'book_set-0-id': '5',
    686702...     'book_set-0-title': 'Flowers of Evil',
    687703...     'book_set-1-title': 'Revue des deux mondes',
    We need to ensure that it is displayed 
    718734>>> data = {
    719735...     'owner_set-TOTAL_FORMS': '2',
    720736...     'owner_set-INITIAL_FORMS': '0',
     737...     'owner_set-MAX_NUM_FORMS': '0',
    721738...     'owner_set-0-auto_id': '',
    722739...     'owner_set-0-name': u'Joe Perry',
    723740...     'owner_set-1-auto_id': '',
    True 
    739756>>> data = {
    740757...     'owner_set-TOTAL_FORMS': '3',
    741758...     'owner_set-INITIAL_FORMS': '1',
     759...     'owner_set-MAX_NUM_FORMS': '0',
    742760...     'owner_set-0-auto_id': u'1',
    743761...     'owner_set-0-name': u'Joe Perry',
    744762...     'owner_set-1-auto_id': '',
    True 
    767785
    768786>>> owner = Owner.objects.get(name=u'Joe Perry')
    769787>>> FormSet = inlineformset_factory(Owner, OwnerProfile, max_num=1, can_delete=False)
    770 
     788>>> FormSet.max_num
     7891
    771790>>> formset = FormSet(instance=owner)
    772791>>> for form in formset.forms:
    773792...     print form.as_p()
    True 
    776795>>> data = {
    777796...     'ownerprofile-TOTAL_FORMS': '1',
    778797...     'ownerprofile-INITIAL_FORMS': '0',
     798...     'ownerprofile-MAX_NUM_FORMS': '1',
    779799...     'ownerprofile-0-owner': '',
    780800...     'ownerprofile-0-age': u'54',
    781801... }
    True 
    784804True
    785805>>> formset.save()
    786806[<OwnerProfile: Joe Perry is 54>]
    787 
    788807>>> formset = FormSet(instance=owner)
    789808>>> for form in formset.forms:
    790809...     print form.as_p()
    True 
    793812>>> data = {
    794813...     'ownerprofile-TOTAL_FORMS': '1',
    795814...     'ownerprofile-INITIAL_FORMS': '1',
     815...     'ownerprofile-MAX_NUM_FORMS': '1',
    796816...     'ownerprofile-0-owner': u'1',
    797817...     'ownerprofile-0-age': u'55',
    798818... }
    True 
    805825# ForeignKey with unique=True should enforce max_num=1
    806826
    807827>>> FormSet = inlineformset_factory(Place, Location, can_delete=False)
     828>>> FormSet.max_num
     8291
    808830>>> formset = FormSet(instance=place)
    809831>>> for form in formset.forms:
    810832...     print form.as_p()
    True 
    826848>>> data = {
    827849...     'form-TOTAL_FORMS': '1',
    828850...     'form-INITIAL_FORMS': '0',
     851...     'form-MAX_NUM_FORMS': '0',
    829852...     'form-0-slug': 'car-red',
    830853... }
    831854>>> formset = FormSet(data)
    True 
    837860>>> data = {
    838861...     'form-TOTAL_FORMS': '1',
    839862...     'form-INITIAL_FORMS': '0',
     863...     'form-MAX_NUM_FORMS': '0',
    840864...     'form-0-slug': 'car-red',
    841865... }
    842866>>> formset = FormSet(data)
    False 
    851875>>> data = {
    852876...     'form-TOTAL_FORMS': '1',
    853877...     'form-INITIAL_FORMS': '0',
     878...     'form-MAX_NUM_FORMS': '0',
    854879...     'form-0-price': u'12.00',
    855880...     'form-0-quantity': '1',
    856881... }
    True 
    863888>>> data = {
    864889...     'form-TOTAL_FORMS': '1',
    865890...     'form-INITIAL_FORMS': '0',
     891...     'form-MAX_NUM_FORMS': '0',
    866892...     'form-0-price': u'12.00',
    867893...     'form-0-quantity': '1',
    868894... }
    False 
    880906>>> data = {
    881907...     'revision_set-TOTAL_FORMS': '1',
    882908...     'revision_set-INITIAL_FORMS': '0',
     909...     'revision_set-MAX_NUM_FORMS': '0',
    883910...     'revision_set-0-repository': repository.pk,
    884911...     'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76',
    885912...     'revision_set-0-DELETE': '',
    True 
    894921>>> data = {
    895922...     'revision_set-TOTAL_FORMS': '1',
    896923...     'revision_set-INITIAL_FORMS': '0',
     924...     'revision_set-MAX_NUM_FORMS': '0',
    897925...     'revision_set-0-repository': repository.pk,
    898926...     'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76',
    899927...     'revision_set-0-DELETE': '',
    False 
    911939>>> data = {
    912940...     'revision_set-TOTAL_FORMS': '1',
    913941...     'revision_set-INITIAL_FORMS': '0',
     942...     'revision_set-MAX_NUM_FORMS': '0',
    914943...     'revision_set-0-repository': repository.pk,
    915944...     'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76',
    916945...     'revision_set-0-DELETE': '',
    False 
    940969>>> data = {
    941970...     'membership_set-TOTAL_FORMS': '1',
    942971...     'membership_set-INITIAL_FORMS': '0',
     972...     'membership_set-MAX_NUM_FORMS': '0',
    943973...     'membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
    944974...     'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
    945975...     'membership_set-0-karma': '',
    True 
    954984>>> filled_data = {
    955985...     'membership_set-TOTAL_FORMS': '1',
    956986...     'membership_set-INITIAL_FORMS': '0',
     987...     'membership_set-MAX_NUM_FORMS': '0',
    957988...     'membership_set-0-date_joined': unicode(one_day_later.strftime('%Y-%m-%d %H:%M:%S')),
    958989...     'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
    959990...     'membership_set-0-karma': '',
    False 
    9761007>>> data = {
    9771008...     'membership_set-TOTAL_FORMS': '1',
    9781009...     'membership_set-INITIAL_FORMS': '0',
     1010...     'membership_set-MAX_NUM_FORMS': '0',
    9791011...     'membership_set-0-date_joined_0': unicode(now.strftime('%Y-%m-%d')),
    9801012...     'membership_set-0-date_joined_1': unicode(now.strftime('%H:%M:%S')),
    9811013...     'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
    True 
    10111043>>> data = {
    10121044...     'form-TOTAL_FORMS': 2,
    10131045...     'form-INITIAL_FORMS': 0,
     1046...     'form-MAX_NUM_FORMS': '0',
    10141047...     'form-0-slug': 'red_car',
    10151048...     'form-1-slug': 'red_car',
    10161049... }
    False 
    10241057>>> data = {
    10251058...     'form-TOTAL_FORMS': 2,
    10261059...     'form-INITIAL_FORMS': 0,
     1060...     'form-MAX_NUM_FORMS': '0',
    10271061...     'form-0-price': '25',
    10281062...     'form-0-quantity': '7',
    10291063...     'form-1-price': '25',
    False 
    10411075>>> data = {
    10421076...     'form-TOTAL_FORMS': '2',
    10431077...     'form-INITIAL_FORMS': '0',
     1078...     'form-MAX_NUM_FORMS': '0',
    10441079...     'form-0-price': '24',
    10451080...     'form-1-price': '24',
    10461081... }
    True 
    10541089>>> data = {
    10551090...     'book_set-TOTAL_FORMS': '2',
    10561091...     'book_set-INITIAL_FORMS': '2',
     1092...     'book_set-MAX_NUM_FORMS': '0',
    10571093...
    10581094...     'book_set-0-title': 'The 2008 Election',
    10591095...     'book_set-0-author': str(author.id),
    False 
    10751111>>> data = {
    10761112...     'form-TOTAL_FORMS': '2',
    10771113...     'form-INITIAL_FORMS': '0',
     1114...     'form-MAX_NUM_FORMS': '0',
    10781115...
    10791116...     'form-0-title': 'blah',
    10801117...     'form-0-slug': 'Morning',
    False 
    10961133>>> data = {
    10971134...     'form-TOTAL_FORMS': '2',
    10981135...     'form-INITIAL_FORMS': '0',
     1136...     'form-MAX_NUM_FORMS': '0',
    10991137...
    11001138...     'form-0-title': 'foo',
    11011139...     'form-0-slug': 'Morning in Prague',
    False 
    11151153>>> data = {
    11161154...     'form-TOTAL_FORMS': '2',
    11171155...     'form-INITIAL_FORMS': '0',
     1156...     'form-MAX_NUM_FORMS': '0',
    11181157...
    11191158...     'form-0-title': 'foo',
    11201159...     '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): 
    99        data = {
    1010            'form-TOTAL_FORMS': u'1',
    1111            'form-INITIAL_FORMS': u'1',
     12            'form-MAX_NUM_FORMS': u'0',
    1213            'form-0-id': str(poet.pk),
    1314            'form-0-name': u'test',
    1415            'form-0-DELETE': u'on',
    class DeletionTests(TestCase): 
    2728        data = {
    2829            'form-TOTAL_FORMS': u'1',
    2930            'form-INITIAL_FORMS': u'0',
     31            'form-MAX_NUM_FORMS': u'0',
    3032            'form-0-id': u'',
    3133            'form-0-name': u'x' * 1000,
    3234        }
    class DeletionTests(TestCase): 
    5355        data = {
    5456            'form-TOTAL_FORMS': u'1',
    5557            'form-INITIAL_FORMS': u'1',
     58            'form-MAX_NUM_FORMS': u'0',
    5659            'form-0-id': u'1',
    5760            'form-0-name': u'x' * 1000,
    5861        }
  • 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): 
    8787            # inline data
    8888            "article_set-TOTAL_FORMS": u"3",
    8989            "article_set-INITIAL_FORMS": u"0",
     90            "article_set-MAX_NUM_FORMS": u"0",
    9091        }
    9192        response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data)
    9293        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
    class AdminViewBasicTest(TestCase): 
    9798        # inline data
    9899        "article_set-TOTAL_FORMS": u"6",
    99100        "article_set-INITIAL_FORMS": u"3",
     101        "article_set-MAX_NUM_FORMS": u"0",
    100102        "article_set-0-id": u"1",
    101103        # there is no title in database, give one here or formset will fail.
    102104        "article_set-0-title": u"Norske bostaver æøå skaper problemer",
    class AdminViewUnicodeTest(TestCase): 
    864866            # inline data
    865867            "chapter_set-TOTAL_FORMS": u"6",
    866868            "chapter_set-INITIAL_FORMS": u"3",
     869            "chapter_set-MAX_NUM_FORMS": u"0",
    867870            "chapter_set-0-id": u"1",
    868871            "chapter_set-0-title": u"Norske bostaver æøå skaper problemer",
    869872            "chapter_set-0-content": u"&lt;p&gt;Svært frustrerende med UnicodeDecodeError&lt;/p&gt;",
    class AdminViewListEditable(TestCase): 
    926929    def test_changelist_input_html(self):
    927930        response = self.client.get('/test_admin/admin/admin_views/person/')
    928931        # 2 inputs per object(the field and the hidden id field) = 6
    929         # 2 management hidden fields = 2
     932        # 3 management hidden fields = 3
    930933        # 4 action inputs (3 regular checkboxes, 1 checkbox to select all)
    931934        # main form submit button = 1
    932935        # search field and search submit button = 2
    933936        # CSRF field = 1
    934937        # field to track 'select all' across paginated views = 1
    935         # 6 + 2 + 4 + 1 + 2 + 1 + 1 = 17 inputs
    936         self.failUnlessEqual(response.content.count("<input"), 17)
     938        # 6 + 3 + 4 + 1 + 2 + 1 + 1 = 18 inputs
     939        self.failUnlessEqual(response.content.count("<input"), 18)
    937940        # 1 select per object = 3 selects
    938941        self.failUnlessEqual(response.content.count("<select"), 4)
    939942
    class AdminViewListEditable(TestCase): 
    941944        data = {
    942945            "form-TOTAL_FORMS": "3",
    943946            "form-INITIAL_FORMS": "3",
     947            "form-MAX_NUM_FORMS": "0",
    944948
    945949            "form-0-gender": "1",
    946950            "form-0-id": "1",
    class AdminViewListEditable(TestCase): 
    961965        data = {
    962966            "form-TOTAL_FORMS": "2",
    963967            "form-INITIAL_FORMS": "2",
     968            "form-MAX_NUM_FORMS": "0",
    964969
    965970            "form-0-id": "1",
    966971            "form-0-gender": "1",
    class AdminViewListEditable(TestCase): 
    978983        data = {
    979984            "form-TOTAL_FORMS": "1",
    980985            "form-INITIAL_FORMS": "1",
     986            "form-MAX_NUM_FORMS": "0",
    981987
    982988            "form-0-id": "1",
    983989            "form-0-gender": "1"
    class AdminViewListEditable(TestCase): 
    9981004        data = {
    9991005            "form-TOTAL_FORMS": "4",
    10001006            "form-INITIAL_FORMS": "4",
     1007            "form-MAX_NUM_FORMS": "0",
    10011008
    10021009            "form-0-order": "14",
    10031010            "form-0-id": "1",
    class AdminInheritedInlinesTest(TestCase): 
    10691076            # inline data
    10701077            "accounts-TOTAL_FORMS": u"1",
    10711078            "accounts-INITIAL_FORMS": u"0",
     1079            "accounts-MAX_NUM_FORMS": u"0",
    10721080            "accounts-0-username": foo_user,
    10731081            "accounts-2-TOTAL_FORMS": u"1",
    10741082            "accounts-2-INITIAL_FORMS": u"0",
     1083            "accounts-2-MAX_NUM_FORMS": u"0",
    10751084            "accounts-2-0-username": bar_user,
    10761085        }
    10771086
    class AdminInheritedInlinesTest(TestCase): 
    10961105
    10971106            "accounts-TOTAL_FORMS": "2",
    10981107            "accounts-INITIAL_FORMS": u"1",
     1108            "accounts-MAX_NUM_FORMS": u"0",
    10991109
    11001110            "accounts-0-username": "%s-1" % foo_user,
    11011111            "accounts-0-account_ptr": "1",
    class AdminInheritedInlinesTest(TestCase): 
    11031113
    11041114            "accounts-2-TOTAL_FORMS": u"2",
    11051115            "accounts-2-INITIAL_FORMS": u"1",
     1116            "accounts-2-MAX_NUM_FORMS": u"0",
    11061117
    11071118            "accounts-2-0-username": "%s-1" % bar_user,
    11081119            "accounts-2-0-account_ptr": "2",
    class AdminInlineFileUploadTest(TestCase): 
    13481359            "name": u"Test Gallery",
    13491360            "pictures-TOTAL_FORMS": u"2",
    13501361            "pictures-INITIAL_FORMS": u"1",
     1362            "pictures-MAX_NUM_FORMS": u"0",
    13511363            "pictures-0-id": u"1",
    13521364            "pictures-0-gallery": u"1",
    13531365            "pictures-0-name": "Test Picture",
    class AdminInlineTests(TestCase): 
    13701382
    13711383            "widget_set-TOTAL_FORMS": "3",
    13721384            "widget_set-INITIAL_FORMS": u"0",
     1385            "widget_set-MAX_NUM_FORMS": u"0",
    13731386            "widget_set-0-id": "",
    13741387            "widget_set-0-owner": "1",
    13751388            "widget_set-0-name": "",
    class AdminInlineTests(TestCase): 
    13821395
    13831396            "doohickey_set-TOTAL_FORMS": "3",
    13841397            "doohickey_set-INITIAL_FORMS": u"0",
     1398            "doohickey_set-MAX_NUM_FORMS": u"0",
    13851399            "doohickey_set-0-owner": "1",
    13861400            "doohickey_set-0-code": "",
    13871401            "doohickey_set-0-name": "",
    class AdminInlineTests(TestCase): 
    13941408
    13951409            "grommet_set-TOTAL_FORMS": "3",
    13961410            "grommet_set-INITIAL_FORMS": u"0",
     1411            "grommet_set-MAX_NUM_FORMS": u"0",
    13971412            "grommet_set-0-code": "",
    13981413            "grommet_set-0-owner": "1",
    13991414            "grommet_set-0-name": "",
    class AdminInlineTests(TestCase): 
    14061421
    14071422            "whatsit_set-TOTAL_FORMS": "3",
    14081423            "whatsit_set-INITIAL_FORMS": u"0",
     1424            "whatsit_set-MAX_NUM_FORMS": u"0",
    14091425            "whatsit_set-0-owner": "1",
    14101426            "whatsit_set-0-index": "",
    14111427            "whatsit_set-0-name": "",
    class AdminInlineTests(TestCase): 
    14181434
    14191435            "fancydoodad_set-TOTAL_FORMS": "3",
    14201436            "fancydoodad_set-INITIAL_FORMS": u"0",
     1437            "fancydoodad_set-MAX_NUM_FORMS": u"0",
    14211438            "fancydoodad_set-0-doodad_ptr": "",
    14221439            "fancydoodad_set-0-owner": "1",
    14231440            "fancydoodad_set-0-name": "",
    class AdminInlineTests(TestCase): 
    14331450
    14341451            "category_set-TOTAL_FORMS": "3",
    14351452            "category_set-INITIAL_FORMS": "0",
     1453            "category_set-MAX_NUM_FORMS": "0",
    14361454            "category_set-0-order": "",
    14371455            "category_set-0-id": "",
    14381456            "category_set-0-collector": "1",
    class AdminInlineTests(TestCase): 
    16241642
    16251643            "category_set-TOTAL_FORMS": "7",
    16261644            "category_set-INITIAL_FORMS": "4",
     1645            "category_set-MAX_NUM_FORMS": "0",
    16271646
    16281647            "category_set-0-order": "14",
    16291648            "category_set-0-id": "1",
    class ReadonlyTest(TestCase): 
    17501769        response = self.client.get('/test_admin/admin/admin_views/post/add/')
    17511770        self.assertEqual(response.status_code, 200)
    17521771        self.assertNotContains(response, 'name="posted"')
    1753         # 3 fields + 2 submit buttons + 2 inline management form fields, + 2
    1754         # hidden fields for inlines + 1 field for the inline
    1755         self.assertEqual(response.content.count("input"), 10)
     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)
    17561775        self.assertContains(response, formats.localize(datetime.date.today()))
    17571776        self.assertContains(response,
    17581777            "<label>Awesomeness level:</label>")
    class ReadonlyTest(TestCase): 
    17731792            "content": "This is an incredible development.",
    17741793            "link_set-TOTAL_FORMS": "1",
    17751794            "link_set-INITIAL_FORMS": "0",
     1795            "link_set-MAX_NUM_FORMS": "0",
    17761796        }
    17771797        response = self.client.post('/test_admin/admin/admin_views/post/add/', data)
    17781798        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. 
    2020
    2121>>> formset = ChoiceFormSet(auto_id=False, prefix='choices')
    2222>>> 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" />
    2424<tr><th>Choice:</th><td><input type="text" name="choices-0-choice" /></td></tr>
    2525<tr><th>Votes:</th><td><input type="text" name="choices-0-votes" /></td></tr>
    2626
    the TOTAL_FORMS field appropriately. 
    3434>>> data = {
    3535...     'choices-TOTAL_FORMS': '1', # the number of forms rendered
    3636...     'choices-INITIAL_FORMS': '0', # the number of forms with initial data
     37...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    3738...     'choices-0-choice': 'Calexico',
    3839...     'choices-0-votes': '100',
    3940... }
    any of the forms. 
    6061>>> data = {
    6162...     'choices-TOTAL_FORMS': '1', # the number of forms rendered
    6263...     'choices-INITIAL_FORMS': '0', # the number of forms with initial data
     64...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    6365...     'choices-0-choice': 'Calexico',
    6466...     'choices-0-votes': '',
    6567... }
    Let's simulate what would happen if we submitted this form. 
    9092>>> data = {
    9193...     'choices-TOTAL_FORMS': '2', # the number of forms rendered
    9294...     'choices-INITIAL_FORMS': '1', # the number of forms with initial data
     95...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    9396...     'choices-0-choice': 'Calexico',
    9497...     'choices-0-votes': '100',
    9598...     'choices-1-choice': '',
    handle that later. 
    111114>>> data = {
    112115...     'choices-TOTAL_FORMS': '2', # the number of forms rendered
    113116...     'choices-INITIAL_FORMS': '1', # the number of forms with initial data
     117...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    114118...     'choices-0-choice': 'Calexico',
    115119...     'choices-0-votes': '100',
    116120...     'choices-1-choice': 'The Decemberists',
    handle that case later. 
    130134>>> data = {
    131135...     'choices-TOTAL_FORMS': '2', # the number of forms rendered
    132136...     'choices-INITIAL_FORMS': '1', # the number of forms with initial data
     137...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    133138...     'choices-0-choice': '', # deleted value
    134139...     'choices-0-votes': '', # deleted value
    135140...     'choices-1-choice': '',
    number of forms to be completed. 
    167172>>> data = {
    168173...     'choices-TOTAL_FORMS': '3', # the number of forms rendered
    169174...     'choices-INITIAL_FORMS': '0', # the number of forms with initial data
     175...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    170176...     'choices-0-choice': '',
    171177...     'choices-0-votes': '',
    172178...     'choices-1-choice': '',
    We can just fill out one of the forms. 
    187193>>> data = {
    188194...     'choices-TOTAL_FORMS': '3', # the number of forms rendered
    189195...     'choices-INITIAL_FORMS': '0', # the number of forms with initial data
     196...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    190197...     'choices-0-choice': 'Calexico',
    191198...     'choices-0-votes': '100',
    192199...     'choices-1-choice': '',
    And once again, if we try to partially complete a form, validation will fail. 
    207214>>> data = {
    208215...     'choices-TOTAL_FORMS': '3', # the number of forms rendered
    209216...     'choices-INITIAL_FORMS': '0', # the number of forms with initial data
     217...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    210218...     'choices-0-choice': 'Calexico',
    211219...     'choices-0-votes': '100',
    212220...     'choices-1-choice': 'The Decemberists',
    To delete something, we just need to set that form's special delete field to 
    274282>>> data = {
    275283...     'choices-TOTAL_FORMS': '3', # the number of forms rendered
    276284...     'choices-INITIAL_FORMS': '2', # the number of forms with initial data
     285...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    277286...     'choices-0-choice': 'Calexico',
    278287...     'choices-0-votes': '100',
    279288...     'choices-0-DELETE': '',
    it's going to be deleted. 
    303312>>> data = {
    304313...     'check-TOTAL_FORMS': '3', # the number of forms rendered
    305314...     'check-INITIAL_FORMS': '2', # the number of forms with initial data
     315...     'check-MAX_NUM_FORMS': '0', # max number of forms
    306316...     'check-0-field': '200',
    307317...     'check-0-DELETE': '',
    308318...     'check-1-field': '50',
    something at the front of the list, you'd need to set it's order to 0. 
    351361>>> data = {
    352362...     'choices-TOTAL_FORMS': '3', # the number of forms rendered
    353363...     'choices-INITIAL_FORMS': '2', # the number of forms with initial data
     364...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    354365...     'choices-0-choice': 'Calexico',
    355366...     'choices-0-votes': '100',
    356367...     'choices-0-ORDER': '1',
    they will be sorted below everything else. 
    377388>>> data = {
    378389...     'choices-TOTAL_FORMS': '4', # the number of forms rendered
    379390...     'choices-INITIAL_FORMS': '3', # the number of forms with initial data
     391...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    380392...     'choices-0-choice': 'Calexico',
    381393...     'choices-0-votes': '100',
    382394...     'choices-0-ORDER': '1',
    Ordering should work with blank fieldsets. 
    406418>>> data = {
    407419...     'choices-TOTAL_FORMS': '3', # the number of forms rendered
    408420...     'choices-INITIAL_FORMS': '0', # the number of forms with initial data
     421...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    409422... }
    410423
    411424>>> formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
    Let's delete Fergie, and put The Decemberists ahead of Calexico. 
    450463>>> data = {
    451464...     'choices-TOTAL_FORMS': '4', # the number of forms rendered
    452465...     'choices-INITIAL_FORMS': '3', # the number of forms with initial data
     466...     'choices-MAX_NUM_FORMS': '0', # max number of forms
    453467...     'choices-0-choice': 'Calexico',
    454468...     'choices-0-votes': '100',
    455469...     'choices-0-ORDER': '1',
    We start out with a some duplicate data. 
    508522>>> data = {
    509523...     'drinks-TOTAL_FORMS': '2', # the number of forms rendered
    510524...     'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
     525...     'drinks-MAX_NUM_FORMS': '0', # max number of forms
    511526...     'drinks-0-name': 'Gin and Tonic',
    512527...     'drinks-1-name': 'Gin and Tonic',
    513528... }
    Make sure we didn't break the valid case. 
    529544>>> data = {
    530545...     'drinks-TOTAL_FORMS': '2', # the number of forms rendered
    531546...     'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
     547...     'drinks-MAX_NUM_FORMS': '0', # max number of forms
    532548...     'drinks-0-name': 'Gin and Tonic',
    533549...     'drinks-1-name': 'Bloody Mary',
    534550... }
  • 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): 
    5858            # inline data
    5959            "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"1",
    6060            "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",
    6162        }
    6263        response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data)
    6364        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
    class GenericAdminViewTest(TestCase): 
    7172            # inline data
    7273            "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"3",
    7374            "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",
    7476            "generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.mp3_media_pk,
    7577            "generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3",
    7678            "generic_inline_admin-media-content_type-object_id-1-id": u"%d" % self.png_media_pk,
    class GenericInlineAdminWithUniqueTogetherTest(TestCase): 
    192194            # inline data
    193195            "generic_inline_admin-phonenumber-content_type-object_id-TOTAL_FORMS": u"1",
    194196            "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",
    195198            "generic_inline_admin-phonenumber-content_type-object_id-0-id": "",
    196199            "generic_inline_admin-phonenumber-content_type-object_id-0-phone_number": "555-555-5555",
    197200        }
  • 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): 
    1010        data = {
    1111            'poem_set-TOTAL_FORMS': u'1',
    1212            'poem_set-INITIAL_FORMS': u'1',
     13            'poem_set-MAX_NUM_FORMS': u'0',
    1314            'poem_set-0-id': str(poem.pk),
    1415            'poem_set-0-poet': str(poet.pk),
    1516            'poem_set-0-name': u'test',
    class DeletionTests(TestCase): 
    3031        data = {
    3132            'poem_set-TOTAL_FORMS': u'1',
    3233            'poem_set-INITIAL_FORMS': u'0',
     34            'poem_set-MAX_NUM_FORMS': u'0',
    3335            'poem_set-0-id': u'',
    3436            'poem_set-0-poem': u'1',
    3537            'poem_set-0-name': u'x' * 1000,
    class DeletionTests(TestCase): 
    5860        data = {
    5961            'poem_set-TOTAL_FORMS': u'1',
    6062            'poem_set-INITIAL_FORMS': u'1',
     63            'poem_set-MAX_NUM_FORMS': u'0',
    6164            'poem_set-0-id': u'1',
    6265            'poem_set-0-poem': u'1',
    6366            'poem_set-0-name': u'x' * 1000,
    class DeletionTests(TestCase): 
    8891        data = {
    8992            'child_set-TOTAL_FORMS': u'1',
    9093            'child_set-INITIAL_FORMS': u'0',
     94            'child_set-MAX_NUM_FORMS': u'0',
    9195            'child_set-0-name': u'child',
    9296        }
    9397        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): 
    2020            'username': u'apollo13',
    2121            'usersite_set-TOTAL_FORMS': u'1',
    2222            'usersite_set-INITIAL_FORMS': u'0',
     23            'usersite_set-MAX_NUM_FORMS': u'0',
    2324            'usersite_set-0-data': u'10',
    2425            'usersite_set-0-user': u'apollo13'
    2526        }
    class InlineFormsetTests(TestCase): 
    4344        data = {
    4445            'usersite_set-TOTAL_FORMS': u'1',
    4546            'usersite_set-INITIAL_FORMS': u'1',
     47            'usersite_set-MAX_NUM_FORMS': u'0',
    4648            'usersite_set-0-id': unicode(usersite[0]['id']),
    4749            'usersite_set-0-data': u'11',
    4850            'usersite_set-0-user': u'apollo13'
    class InlineFormsetTests(TestCase): 
    6062        data = {
    6163            'usersite_set-TOTAL_FORMS': u'2',
    6264            'usersite_set-INITIAL_FORMS': u'1',
     65            'usersite_set-MAX_NUM_FORMS': u'0',
    6366            'usersite_set-0-id': unicode(usersite[0]['id']),
    6467            'usersite_set-0-data': u'11',
    6568            'usersite_set-0-user': u'apollo13',
    class InlineFormsetTests(TestCase): 
    9295            'name': u"Guido's House of Pasta",
    9396            'manager_set-TOTAL_FORMS': u'1',
    9497            'manager_set-INITIAL_FORMS': u'0',
     98            'manager_set-MAX_NUM_FORMS': u'0',
    9599            'manager_set-0-name': u'Guido Van Rossum'
    96100        }
    97101        restaurant = User()
    class InlineFormsetTests(TestCase): 
    113117        data = {
    114118            'manager_set-TOTAL_FORMS': u'1',
    115119            'manager_set-INITIAL_FORMS': u'1',
     120            'manager_set-MAX_NUM_FORMS': u'0',
    116121            'manager_set-0-id': unicode(manager[0]['id']),
    117122            'manager_set-0-name': u'Terry Gilliam'
    118123        }
    class InlineFormsetTests(TestCase): 
    128133        data = {
    129134            'manager_set-TOTAL_FORMS': u'2',
    130135            'manager_set-INITIAL_FORMS': u'1',
     136            'manager_set-MAX_NUM_FORMS': u'0',
    131137            'manager_set-0-id': unicode(manager[0]['id']),
    132138            'manager_set-0-name': u'Terry Gilliam',
    133139            'manager_set-1-name': u'John Cleese'
Back to Top