Ticket #12749: t12749.draft-fix.diff

File t12749.draft-fix.diff, 4.7 KB (added by russellm, 5 years ago)

Draft fix; passes nessita's test, but breaks others in model_formsets

  • django/db/models/fields/related.py

    diff -r f681ed7ea9ad django/db/models/fields/related.py
    a b  
    824824    def validate(self, value, model_instance):
    825825        if self.rel.parent_link:
    826826            return
    827         # Don't validate the field if a value wasn't supplied. This is
    828         # generally the case when saving new inlines in the admin.
    829         # See #12507.
    830         if value is None:
    831             return
    832827        super(ForeignKey, self).validate(value, model_instance)
    833828        if not value:
    834829            return
  • django/forms/models.py

    diff -r f681ed7ea9ad django/forms/models.py
    a b  
    309309                field_value = self.cleaned_data.get(field, None)
    310310                if not f.blank and not form_field.required and field_value in EMPTY_VALUES:
    311311                    exclude.append(f.name)
     312                elif isinstance(form_field, InlineForeignKeyField):
     313                    # Don't validate the field if it is the inlined Foreign Key,
     314                    # and we are saving a new object.
     315                    # See #12507 and #12749.
     316                    if self.instance.pk is None:
     317                        exclude.append(f.name)
    312318        return exclude
    313319
    314320    def clean(self):
     
    316322        return self.cleaned_data
    317323
    318324    def _post_clean(self):
    319         exclude = self._get_validation_exclusions()
    320325        opts = self._meta
    321 
    322326        # Update the model instance with self.cleaned_data.
    323327        self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
    324328
     329        exclude = self._get_validation_exclusions()
     330
    325331        # Clean the model instance's fields.
    326332        try:
    327333            self.instance.clean_fields(exclude=exclude)
     
    762768        unique_check = [field for field in unique_check if field != self.fk.name]
    763769        return super(BaseInlineFormSet, self).get_unique_error_message(unique_check)
    764770
     771
    765772def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
    766773    """
    767774    Finds and returns the ForeignKey from model to parent if there is one
  • tests/regressiontests/admin_inlines/models.py

    diff -r f681ed7ea9ad tests/regressiontests/admin_inlines/models.py
    a b  
    8888# only Inline media
    8989admin.site.register(Holder3, inlines=[InnerInline3])
    9090
     91# Models for #12749
     92
     93class Person(models.Model):
     94    firstname = models.CharField(max_length=15)
     95
     96class OutfitItem(models.Model):
     97    name = models.CharField(max_length=15)
     98
     99class Fashionista(models.Model):
     100    person = models.OneToOneField(Person, primary_key=True)
     101    weaknesses = models.ManyToManyField(OutfitItem, through='ShoppingWeakness', blank=True)
     102
     103class ShoppingWeakness(models.Model):
     104    fashionista = models.ForeignKey(Fashionista)
     105    item = models.ForeignKey(OutfitItem)
     106
     107class InlineWeakness(admin.TabularInline):
     108    model = ShoppingWeakness
     109    extra = 1
     110
     111admin.site.register(Fashionista, inlines=[InlineWeakness])
     112
     113
    91114__test__ = {'API_TESTS': """
    92115
    93116# Regression test for #9362
  • tests/regressiontests/admin_inlines/tests.py

    diff -r f681ed7ea9ad tests/regressiontests/admin_inlines/tests.py
    a b  
    33# local test models
    44from models import Holder, Inner, InnerInline
    55from models import Holder2, Inner2, Holder3, Inner3
    6 
     6from models import Person, OutfitItem, Fashionista
    77
    88class TestInline(TestCase):
    99    fixtures = ['admin-views-users.xml']
     
    3838                                   % holder.id)
    3939        self.assertContains(response, '<label>Inner readonly label:</label>')
    4040
     41    def test_inline_primary(self):
     42        person = Person.objects.create(firstname='Imelda')
     43        item = OutfitItem.objects.create(name='Shoes')
     44        # Imelda likes shoes, but can't cary her own bags.
     45        data = {
     46            'shoppingweakness_set-TOTAL_FORMS': 1,
     47            'shoppingweakness_set-INITIAL_FORMS': 0,
     48            'shoppingweakness_set-MAX_NUM_FORMS': 0,
     49            '_save': u'Save',
     50            'person': person.id,
     51            'max_weight': 0,
     52            'shoppingweakness_set-0-item': item.id,
     53        }
     54        response = self.client.post('/test_admin/admin/admin_inlines/fashionista/add/', data)
     55        self.assertEqual(response.status_code, 302)
     56        self.assertEqual(len(Fashionista.objects.filter(person__firstname='Imelda')), 1)
    4157
    4258class TestInlineMedia(TestCase):
    4359    fixtures = ['admin-views-users.xml']
Back to Top