diff --git a/django/contrib/admin/media/js/inlines.js b/django/contrib/admin/media/js/inlines.js index 4e397b6..1f5933f 100644 --- a/django/contrib/admin/media/js/inlines.js +++ b/django/contrib/admin/media/js/inlines.js @@ -56,7 +56,7 @@ var template = $("#" + options.prefix + "-empty"); var row = template.clone(true).get(0); $(row).removeClass(options.emptyCssClass).removeAttr("id").insertBefore($(template)); - $(row).html($(row).html().replace(/__prefix__/g, nextIndex)); + $(row).html($(row).html().replace(new RegExp(options.empty_form_prefix, "g"), nextIndex)); $(row).addClass(options.formCssClass).attr("id", options.prefix + nextIndex); if ($(row).is("TR")) { // If the forms are laid out in table rows, insert @@ -118,6 +118,7 @@ /* Setup plugin defaults */ $.fn.formset.defaults = { prefix: "form", // The form prefix for your django formset + empty_form_prefix: "__prefix__",// The magic prefix bit on the empty form. addText: "add another", // Text for the add link deleteText: "remove", // Text for the delete link addCssClass: "add-row", // CSS class applied to the add link diff --git a/django/contrib/admin/templates/admin/edit_inline/stacked.html b/django/contrib/admin/templates/admin/edit_inline/stacked.html index fb112a0..81879d0 100644 --- a/django/contrib/admin/templates/admin/edit_inline/stacked.html +++ b/django/contrib/admin/templates/admin/edit_inline/stacked.html @@ -50,6 +50,7 @@ } $(rows).formset({ prefix: "{{ inline_admin_formset.formset.prefix }}", + empty_form_prefix: "{{ inline_admin_formset.formset.empty_form_prefix }}", addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}", formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}", deleteCssClass: "inline-deletelink", diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html index dc9552f..d56944a 100644 --- a/django/contrib/admin/templates/admin/edit_inline/tabular.html +++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html @@ -96,6 +96,7 @@ } $(rows).formset({ prefix: "{{ inline_admin_formset.formset.prefix }}", + empty_form_prefix: "{{ inline_admin_formset.formset.empty_form_prefix }}", addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}", formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}", deleteCssClass: "inline-deletelink", diff --git a/django/forms/formsets.py b/django/forms/formsets.py index ec14f81..03aa7ba 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -32,6 +32,8 @@ class BaseFormSet(StrAndUnicode): """ A collection of instances of the same Form class. """ + empty_form_prefix = '__prefix__' + def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList): self.is_bound = data is not None or files is not None @@ -125,7 +127,7 @@ class BaseFormSet(StrAndUnicode): def _get_empty_form(self, **kwargs): defaults = { 'auto_id': self.auto_id, - 'prefix': self.add_prefix('__prefix__'), + 'prefix': self.add_prefix(self.empty_form_prefix), 'empty_permitted': True, } if self.data or self.files: diff --git a/tests/regressiontests/forms/formsets.py b/tests/regressiontests/forms/formsets.py index 3eecb7f..ae54d80 100644 --- a/tests/regressiontests/forms/formsets.py +++ b/tests/regressiontests/forms/formsets.py @@ -1,4 +1,37 @@ # -*- coding: utf-8 -*- + +from django import forms +from django.forms.formsets import formset_factory +from django.forms.models import inlineformset_factory +from django.test import TestCase + +from models import Form, FormPage, Field + + +class EmptyFormTestCase(TestCase): + def test_custom_empty_form_prefix(self): + class BasicForm(forms.Form): + value = forms.CharField() + + FormSet = formset_factory(BasicForm) + FormSet.empty_form_prefix = "__pony__" + self.assertEqual(str(FormSet().empty_form), """