[1.0.X] Fixed #8882 -- When a foreign key is among the unique_together fields in an inline formset properly handle it.
Backport of r9297 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9298 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4931612727
commit
7b80af625b
|
@ -109,6 +109,8 @@ class InlineAdminFormSet(object):
|
||||||
|
|
||||||
def fields(self):
|
def fields(self):
|
||||||
for field_name in flatten_fieldsets(self.fieldsets):
|
for field_name in flatten_fieldsets(self.fieldsets):
|
||||||
|
if self.formset.fk.name == field_name:
|
||||||
|
continue
|
||||||
yield self.formset.form.base_fields[field_name]
|
yield self.formset.form.base_fields[field_name]
|
||||||
|
|
||||||
def _media(self):
|
def _media(self):
|
||||||
|
@ -130,6 +132,10 @@ class InlineAdminForm(AdminForm):
|
||||||
self.show_url = original and hasattr(original, 'get_absolute_url')
|
self.show_url = original and hasattr(original, 'get_absolute_url')
|
||||||
super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields)
|
super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for name, options in self.fieldsets:
|
||||||
|
yield InlineFieldset(self.formset, self.form, name, **options)
|
||||||
|
|
||||||
def field_count(self):
|
def field_count(self):
|
||||||
# tabular.html uses this function for colspan value.
|
# tabular.html uses this function for colspan value.
|
||||||
num_of_fields = 1 # always has at least one field
|
num_of_fields = 1 # always has at least one field
|
||||||
|
@ -142,6 +148,9 @@ class InlineAdminForm(AdminForm):
|
||||||
|
|
||||||
def pk_field(self):
|
def pk_field(self):
|
||||||
return AdminField(self.form, self.formset._pk_field.name, False)
|
return AdminField(self.form, self.formset._pk_field.name, False)
|
||||||
|
|
||||||
|
def fk_field(self):
|
||||||
|
return AdminField(self.form, self.formset.fk.name, False)
|
||||||
|
|
||||||
def deletion_field(self):
|
def deletion_field(self):
|
||||||
from django.forms.formsets import DELETION_FIELD_NAME
|
from django.forms.formsets import DELETION_FIELD_NAME
|
||||||
|
@ -151,6 +160,17 @@ class InlineAdminForm(AdminForm):
|
||||||
from django.forms.formsets import ORDERING_FIELD_NAME
|
from django.forms.formsets import ORDERING_FIELD_NAME
|
||||||
return AdminField(self.form, ORDERING_FIELD_NAME, False)
|
return AdminField(self.form, ORDERING_FIELD_NAME, False)
|
||||||
|
|
||||||
|
class InlineFieldset(Fieldset):
|
||||||
|
def __init__(self, formset, *args, **kwargs):
|
||||||
|
self.formset = formset
|
||||||
|
super(InlineFieldset, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for field in self.fields:
|
||||||
|
if self.formset.fk.name == field:
|
||||||
|
continue
|
||||||
|
yield Fieldline(self.form, field)
|
||||||
|
|
||||||
class AdminErrorList(forms.util.ErrorList):
|
class AdminErrorList(forms.util.ErrorList):
|
||||||
"""
|
"""
|
||||||
Stores all errors for the form/formsets in an add/change stage view.
|
Stores all errors for the form/formsets in an add/change stage view.
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
{% include "admin/includes/fieldset.html" %}
|
{% include "admin/includes/fieldset.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{{ inline_admin_form.pk_field.field }}
|
{{ inline_admin_form.pk_field.field }}
|
||||||
|
{{ inline_admin_form.fk_field.field }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
|
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
|
||||||
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original.content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
|
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original.content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
|
||||||
</p>{% endif %}
|
</p>{% endif %}
|
||||||
{{ inline_admin_form.pk_field.field }}
|
{{ inline_admin_form.pk_field.field }} {{ inline_admin_form.fk_field.field }}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{% for fieldset in inline_admin_form %}
|
{% for fieldset in inline_admin_form %}
|
||||||
{% for line in fieldset %}
|
{% for line in fieldset %}
|
||||||
|
|
|
@ -3,7 +3,7 @@ Helper functions for creating Form classes from Django models
|
||||||
and database field objects.
|
and database field objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode, force_unicode
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
from django.utils.text import get_text_list, capfirst
|
from django.utils.text import get_text_list, capfirst
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -468,7 +468,7 @@ class BaseInlineFormSet(BaseModelFormSet):
|
||||||
# creating new instances
|
# creating new instances
|
||||||
form.data[form.add_prefix(self._pk_field.name)] = None
|
form.data[form.add_prefix(self._pk_field.name)] = None
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""
|
"""
|
||||||
Returns this FormSet's queryset, but restricted to children of
|
Returns this FormSet's queryset, but restricted to children of
|
||||||
|
@ -485,7 +485,9 @@ class BaseInlineFormSet(BaseModelFormSet):
|
||||||
def add_fields(self, form, index):
|
def add_fields(self, form, index):
|
||||||
super(BaseInlineFormSet, self).add_fields(form, index)
|
super(BaseInlineFormSet, self).add_fields(form, index)
|
||||||
if self._pk_field == self.fk:
|
if self._pk_field == self.fk:
|
||||||
form.fields[self._pk_field.name] = IntegerField(required=False, widget=HiddenInput)
|
form.fields[self._pk_field.name] = InlineForeignKeyField(self.instance, pk_field=True)
|
||||||
|
else:
|
||||||
|
form.fields[self.fk.name] = InlineForeignKeyField(self.instance, label=form.fields[self.fk.name].label)
|
||||||
|
|
||||||
def _get_foreign_key(parent_model, model, fk_name=None):
|
def _get_foreign_key(parent_model, model, fk_name=None):
|
||||||
"""
|
"""
|
||||||
|
@ -537,11 +539,6 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
|
||||||
# enforce a max_num=1 when the foreign key to the parent model is unique.
|
# enforce a max_num=1 when the foreign key to the parent model is unique.
|
||||||
if fk.unique:
|
if fk.unique:
|
||||||
max_num = 1
|
max_num = 1
|
||||||
if exclude is not None:
|
|
||||||
exclude = list(exclude)
|
|
||||||
exclude.append(fk.name)
|
|
||||||
else:
|
|
||||||
exclude = [fk.name]
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'form': form,
|
'form': form,
|
||||||
'formfield_callback': formfield_callback,
|
'formfield_callback': formfield_callback,
|
||||||
|
@ -560,6 +557,41 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
|
||||||
|
|
||||||
# Fields #####################################################################
|
# Fields #####################################################################
|
||||||
|
|
||||||
|
class InlineForeignKeyHiddenInput(HiddenInput):
|
||||||
|
def _has_changed(self, initial, data):
|
||||||
|
return False
|
||||||
|
|
||||||
|
class InlineForeignKeyField(Field):
|
||||||
|
"""
|
||||||
|
A basic integer field that deals with validating the given value to a
|
||||||
|
given parent instance in an inline.
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid_choice': _(u'The inline foreign key did not match the parent instance primary key.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, parent_instance, *args, **kwargs):
|
||||||
|
self.parent_instance = parent_instance
|
||||||
|
self.pk_field = kwargs.pop("pk_field", False)
|
||||||
|
if self.parent_instance is not None:
|
||||||
|
kwargs["initial"] = self.parent_instance.pk
|
||||||
|
kwargs["required"] = False
|
||||||
|
kwargs["widget"] = InlineForeignKeyHiddenInput
|
||||||
|
super(InlineForeignKeyField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
if value in EMPTY_VALUES:
|
||||||
|
if self.pk_field:
|
||||||
|
return None
|
||||||
|
# if there is no value act as we did before.
|
||||||
|
return self.parent_instance
|
||||||
|
# ensure the we compare the values as equal types.
|
||||||
|
if force_unicode(value) != force_unicode(self.parent_instance.pk):
|
||||||
|
raise ValidationError(self.error_messages['invalid_choice'])
|
||||||
|
if self.pk_field:
|
||||||
|
return self.parent_instance.pk
|
||||||
|
return self.parent_instance
|
||||||
|
|
||||||
class ModelChoiceIterator(object):
|
class ModelChoiceIterator(object):
|
||||||
def __init__(self, field):
|
def __init__(self, field):
|
||||||
self.field = field
|
self.field = field
|
||||||
|
|
|
@ -96,6 +96,24 @@ class Price(models.Model):
|
||||||
class MexicanRestaurant(Restaurant):
|
class MexicanRestaurant(Restaurant):
|
||||||
serves_tacos = models.BooleanField()
|
serves_tacos = models.BooleanField()
|
||||||
|
|
||||||
|
# models for testing unique_together validation when a fk is involved and
|
||||||
|
# using inlineformset_factory.
|
||||||
|
class Repository(models.Model):
|
||||||
|
name = models.CharField(max_length=25)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Revision(models.Model):
|
||||||
|
repository = models.ForeignKey(Repository)
|
||||||
|
revision = models.CharField(max_length=40)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = (("repository", "revision"),)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u"%s (%s)" % (self.revision, unicode(self.repository))
|
||||||
|
|
||||||
# models for testing callable defaults (see bug #7975). If you define a model
|
# models for testing callable defaults (see bug #7975). If you define a model
|
||||||
# with a callable default value, you cannot rely on the initial value in a
|
# with a callable default value, you cannot rely on the initial value in a
|
||||||
# form.
|
# form.
|
||||||
|
@ -375,9 +393,9 @@ admin system's edit inline functionality works.
|
||||||
>>> formset = AuthorBooksFormSet(instance=author)
|
>>> formset = AuthorBooksFormSet(instance=author)
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" maxlength="100" /><input type="hidden" name="book_set-0-id" id="id_book_set-0-id" /></p>
|
<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" maxlength="100" /><input type="hidden" name="book_set-0-author" value="1" id="id_book_set-0-author" /><input type="hidden" name="book_set-0-id" id="id_book_set-0-id" /></p>
|
||||||
<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>
|
<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-author" value="1" id="id_book_set-1-author" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>
|
||||||
<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>
|
<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-author" value="1" id="id_book_set-2-author" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>
|
||||||
|
|
||||||
>>> data = {
|
>>> data = {
|
||||||
... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered
|
... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered
|
||||||
|
@ -409,9 +427,9 @@ book.
|
||||||
>>> formset = AuthorBooksFormSet(instance=author)
|
>>> formset = AuthorBooksFormSet(instance=author)
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" value="Les Fleurs du Mal" maxlength="100" /><input type="hidden" name="book_set-0-id" value="1" id="id_book_set-0-id" /></p>
|
<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" value="Les Fleurs du Mal" maxlength="100" /><input type="hidden" name="book_set-0-author" value="1" id="id_book_set-0-author" /><input type="hidden" name="book_set-0-id" value="1" id="id_book_set-0-id" /></p>
|
||||||
<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>
|
<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-author" value="1" id="id_book_set-1-author" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>
|
||||||
<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>
|
<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-author" value="1" id="id_book_set-2-author" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>
|
||||||
|
|
||||||
>>> data = {
|
>>> data = {
|
||||||
... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered
|
... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered
|
||||||
|
@ -454,7 +472,7 @@ This is used in the admin for save_as functionality.
|
||||||
True
|
True
|
||||||
|
|
||||||
>>> new_author = Author.objects.create(name='Charles Baudelaire')
|
>>> new_author = Author.objects.create(name='Charles Baudelaire')
|
||||||
>>> formset.instance = new_author
|
>>> formset = AuthorBooksFormSet(data, instance=new_author, save_as_new=True)
|
||||||
>>> [book for book in formset.save() if book.author.pk == new_author.pk]
|
>>> [book for book in formset.save() if book.author.pk == new_author.pk]
|
||||||
[<Book: Les Fleurs du Mal>, <Book: Le Spleen de Paris>]
|
[<Book: Les Fleurs du Mal>, <Book: Le Spleen de Paris>]
|
||||||
|
|
||||||
|
@ -463,8 +481,8 @@ Test using a custom prefix on an inline formset.
|
||||||
>>> formset = AuthorBooksFormSet(prefix="test")
|
>>> formset = AuthorBooksFormSet(prefix="test")
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_test-0-title">Title:</label> <input id="id_test-0-title" type="text" name="test-0-title" maxlength="100" /><input type="hidden" name="test-0-id" id="id_test-0-id" /></p>
|
<p><label for="id_test-0-title">Title:</label> <input id="id_test-0-title" type="text" name="test-0-title" maxlength="100" /><input type="hidden" name="test-0-author" id="id_test-0-author" /><input type="hidden" name="test-0-id" id="id_test-0-id" /></p>
|
||||||
<p><label for="id_test-1-title">Title:</label> <input id="id_test-1-title" type="text" name="test-1-title" maxlength="100" /><input type="hidden" name="test-1-id" id="id_test-1-id" /></p>
|
<p><label for="id_test-1-title">Title:</label> <input id="id_test-1-title" type="text" name="test-1-title" maxlength="100" /><input type="hidden" name="test-1-author" id="id_test-1-author" /><input type="hidden" name="test-1-id" id="id_test-1-id" /></p>
|
||||||
|
|
||||||
# Test a custom primary key ###################################################
|
# Test a custom primary key ###################################################
|
||||||
|
|
||||||
|
@ -486,8 +504,8 @@ We need to ensure that it is displayed
|
||||||
>>> formset = FormSet(instance=place)
|
>>> formset = FormSet(instance=place)
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_owner_set-0-name">Name:</label> <input id="id_owner_set-0-name" type="text" name="owner_set-0-name" maxlength="100" /><input type="hidden" name="owner_set-0-auto_id" id="id_owner_set-0-auto_id" /></p>
|
<p><label for="id_owner_set-0-name">Name:</label> <input id="id_owner_set-0-name" type="text" name="owner_set-0-name" maxlength="100" /><input type="hidden" name="owner_set-0-place" value="1" id="id_owner_set-0-place" /><input type="hidden" name="owner_set-0-auto_id" id="id_owner_set-0-auto_id" /></p>
|
||||||
<p><label for="id_owner_set-1-name">Name:</label> <input id="id_owner_set-1-name" type="text" name="owner_set-1-name" maxlength="100" /><input type="hidden" name="owner_set-1-auto_id" id="id_owner_set-1-auto_id" /></p>
|
<p><label for="id_owner_set-1-name">Name:</label> <input id="id_owner_set-1-name" type="text" name="owner_set-1-name" maxlength="100" /><input type="hidden" name="owner_set-1-place" value="1" id="id_owner_set-1-place" /><input type="hidden" name="owner_set-1-auto_id" id="id_owner_set-1-auto_id" /></p>
|
||||||
|
|
||||||
>>> data = {
|
>>> data = {
|
||||||
... 'owner_set-TOTAL_FORMS': '2',
|
... 'owner_set-TOTAL_FORMS': '2',
|
||||||
|
@ -506,9 +524,9 @@ True
|
||||||
>>> formset = FormSet(instance=place)
|
>>> formset = FormSet(instance=place)
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_owner_set-0-name">Name:</label> <input id="id_owner_set-0-name" type="text" name="owner_set-0-name" value="Joe Perry" maxlength="100" /><input type="hidden" name="owner_set-0-auto_id" value="1" id="id_owner_set-0-auto_id" /></p>
|
<p><label for="id_owner_set-0-name">Name:</label> <input id="id_owner_set-0-name" type="text" name="owner_set-0-name" value="Joe Perry" maxlength="100" /><input type="hidden" name="owner_set-0-place" value="1" id="id_owner_set-0-place" /><input type="hidden" name="owner_set-0-auto_id" value="1" id="id_owner_set-0-auto_id" /></p>
|
||||||
<p><label for="id_owner_set-1-name">Name:</label> <input id="id_owner_set-1-name" type="text" name="owner_set-1-name" maxlength="100" /><input type="hidden" name="owner_set-1-auto_id" id="id_owner_set-1-auto_id" /></p>
|
<p><label for="id_owner_set-1-name">Name:</label> <input id="id_owner_set-1-name" type="text" name="owner_set-1-name" maxlength="100" /><input type="hidden" name="owner_set-1-place" value="1" id="id_owner_set-1-place" /><input type="hidden" name="owner_set-1-auto_id" id="id_owner_set-1-auto_id" /></p>
|
||||||
<p><label for="id_owner_set-2-name">Name:</label> <input id="id_owner_set-2-name" type="text" name="owner_set-2-name" maxlength="100" /><input type="hidden" name="owner_set-2-auto_id" id="id_owner_set-2-auto_id" /></p>
|
<p><label for="id_owner_set-2-name">Name:</label> <input id="id_owner_set-2-name" type="text" name="owner_set-2-name" maxlength="100" /><input type="hidden" name="owner_set-2-place" value="1" id="id_owner_set-2-place" /><input type="hidden" name="owner_set-2-auto_id" id="id_owner_set-2-auto_id" /></p>
|
||||||
|
|
||||||
>>> data = {
|
>>> data = {
|
||||||
... 'owner_set-TOTAL_FORMS': '3',
|
... 'owner_set-TOTAL_FORMS': '3',
|
||||||
|
@ -545,7 +563,7 @@ True
|
||||||
>>> formset = FormSet(instance=owner)
|
>>> formset = FormSet(instance=owner)
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_ownerprofile-0-age">Age:</label> <input type="text" name="ownerprofile-0-age" id="id_ownerprofile-0-age" /><input type="hidden" name="ownerprofile-0-owner" id="id_ownerprofile-0-owner" /></p>
|
<p><label for="id_ownerprofile-0-age">Age:</label> <input type="text" name="ownerprofile-0-age" id="id_ownerprofile-0-age" /><input type="hidden" name="ownerprofile-0-owner" value="1" id="id_ownerprofile-0-owner" /></p>
|
||||||
|
|
||||||
>>> data = {
|
>>> data = {
|
||||||
... 'ownerprofile-TOTAL_FORMS': '1',
|
... 'ownerprofile-TOTAL_FORMS': '1',
|
||||||
|
@ -583,7 +601,7 @@ True
|
||||||
>>> for form in formset.forms:
|
>>> for form in formset.forms:
|
||||||
... print form.as_p()
|
... print form.as_p()
|
||||||
<p><label for="id_location_set-0-lat">Lat:</label> <input id="id_location_set-0-lat" type="text" name="location_set-0-lat" maxlength="100" /></p>
|
<p><label for="id_location_set-0-lat">Lat:</label> <input id="id_location_set-0-lat" type="text" name="location_set-0-lat" maxlength="100" /></p>
|
||||||
<p><label for="id_location_set-0-lon">Lon:</label> <input id="id_location_set-0-lon" type="text" name="location_set-0-lon" maxlength="100" /><input type="hidden" name="location_set-0-id" id="id_location_set-0-id" /></p>
|
<p><label for="id_location_set-0-lon">Lon:</label> <input id="id_location_set-0-lon" type="text" name="location_set-0-lon" maxlength="100" /><input type="hidden" name="location_set-0-place" value="1" id="id_location_set-0-place" /><input type="hidden" name="location_set-0-id" id="id_location_set-0-id" /></p>
|
||||||
|
|
||||||
# Foreign keys in parents ########################################
|
# Foreign keys in parents ########################################
|
||||||
|
|
||||||
|
@ -646,6 +664,38 @@ False
|
||||||
>>> formset.errors
|
>>> formset.errors
|
||||||
[{'__all__': [u'Price with this Price and Quantity already exists.']}]
|
[{'__all__': [u'Price with this Price and Quantity already exists.']}]
|
||||||
|
|
||||||
|
# unique_together with inlineformset_factory
|
||||||
|
# Also see bug #8882.
|
||||||
|
|
||||||
|
>>> repository = Repository.objects.create(name=u'Test Repo')
|
||||||
|
>>> FormSet = inlineformset_factory(Repository, Revision, extra=1)
|
||||||
|
>>> data = {
|
||||||
|
... 'revision_set-TOTAL_FORMS': '1',
|
||||||
|
... 'revision_set-INITIAL_FORMS': '0',
|
||||||
|
... 'revision_set-0-repository': repository.pk,
|
||||||
|
... 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76',
|
||||||
|
... 'revision_set-0-DELETE': '',
|
||||||
|
... }
|
||||||
|
>>> formset = FormSet(data, instance=repository)
|
||||||
|
>>> formset.is_valid()
|
||||||
|
True
|
||||||
|
>>> formset.save()
|
||||||
|
[<Revision: 146239817507f148d448db38840db7c3cbf47c76 (Test Repo)>]
|
||||||
|
|
||||||
|
# attempt to save the same revision against against the same repo.
|
||||||
|
>>> data = {
|
||||||
|
... 'revision_set-TOTAL_FORMS': '1',
|
||||||
|
... 'revision_set-INITIAL_FORMS': '0',
|
||||||
|
... 'revision_set-0-repository': repository.pk,
|
||||||
|
... 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76',
|
||||||
|
... 'revision_set-0-DELETE': '',
|
||||||
|
... }
|
||||||
|
>>> formset = FormSet(data, instance=repository)
|
||||||
|
>>> formset.is_valid()
|
||||||
|
False
|
||||||
|
>>> formset.errors
|
||||||
|
[{'__all__': [u'Revision with this Repository and Revision already exists.']}]
|
||||||
|
|
||||||
# Use of callable defaults (see bug #7975).
|
# Use of callable defaults (see bug #7975).
|
||||||
|
|
||||||
>>> person = Person.objects.create(name='Ringo')
|
>>> person = Person.objects.create(name='Ringo')
|
||||||
|
@ -660,7 +710,7 @@ False
|
||||||
>>> now = form.fields['date_joined'].initial
|
>>> now = form.fields['date_joined'].initial
|
||||||
>>> print form.as_p()
|
>>> print form.as_p()
|
||||||
<p><label for="id_membership_set-0-date_joined">Date joined:</label> <input type="text" name="membership_set-0-date_joined" value="..." id="id_membership_set-0-date_joined" /><input type="hidden" name="initial-membership_set-0-date_joined" value="..." id="id_membership_set-0-date_joined" /></p>
|
<p><label for="id_membership_set-0-date_joined">Date joined:</label> <input type="text" name="membership_set-0-date_joined" value="..." id="id_membership_set-0-date_joined" /><input type="hidden" name="initial-membership_set-0-date_joined" value="..." id="id_membership_set-0-date_joined" /></p>
|
||||||
<p><label for="id_membership_set-0-karma">Karma:</label> <input type="text" name="membership_set-0-karma" id="id_membership_set-0-karma" /><input type="hidden" name="membership_set-0-id" id="id_membership_set-0-id" /></p>
|
<p><label for="id_membership_set-0-karma">Karma:</label> <input type="text" name="membership_set-0-karma" id="id_membership_set-0-karma" /><input type="hidden" name="membership_set-0-person" value="1" id="id_membership_set-0-person" /><input type="hidden" name="membership_set-0-id" id="id_membership_set-0-id" /></p>
|
||||||
|
|
||||||
# test for validation with callable defaults. Validations rely on hidden fields
|
# test for validation with callable defaults. Validations rely on hidden fields
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue