#25139: ModelFormSet: allow swapping unique values
-----------------------------+--------------------
     Reporter:  jdufresne    |      Owner:  nobody
         Type:  New feature  |     Status:  new
    Component:  Forms        |    Version:  master
     Severity:  Normal       |   Keywords:
 Triage Stage:  Unreviewed   |  Has patch:  0
Easy pickings:  0            |      UI/UX:  0
-----------------------------+--------------------
 As a user, I would expect to be able to swap ''unique'' values in an HTML
 form backed by a ModelFormSet. Turns out, this is not the case. The user
 must do a two step process of first setting the values to temporary value,
 then swapping the values. I have created a test case in the Django project
 that demonstrates my expectation in tests/model_formsets/tests.py:

 {{{
     def test_swap_unique_values(self):
         p0 = Product.objects.create(slug='car-red')
         p1 = Product.objects.create(slug='car-blue')
         FormSet = modelformset_factory(Product, fields="__all__")
         data = {
             'form-TOTAL_FORMS': '2',
             'form-INITIAL_FORMS': '2',
             # Swap slug values.
             'form-0-id': p0.pk,
             'form-0-slug': 'car-blue',
             'form-1-id': p1.pk,
             'form-1-slug': 'car-red',
         }
         formset = FormSet(data)
         self.assertTrue(formset.is_valid())
         formset.save()

         p0 = Product.objects.get(pk=p0.pk)
         self.assertEquals(p0.slug, 'car-blue')
         p1 = Product.objects.get(pk=p1.pk)
         self.assertEquals(p1.slug, 'car-red')
 }}}

 However, the form fails to validate on the is_valid() line with the
 message "Product with this Slug already exists.".

 When thinking about the details, I understand why this happens. But I
 don't think it should error in this way. Swapping values is a convenience
 that a program can handle without the intervention of a human.

 Knowing that in the end all values will be unique, I think the Django form
 engine should go ahead with the steps necessary to get there. I think it
 is reasonable for a user to expect that they could swap unique values
 through an HTML form in this way.

 As a point of reference, the following test passes. It demonstrates a user
 using temporary values.

 {{{
     def test_swap_unique_values_two_step(self):
         p0 = Product.objects.create(slug='car-red')
         p1 = Product.objects.create(slug='car-blue')
         FormSet = modelformset_factory(Product, fields="__all__")
         data = {
             'form-TOTAL_FORMS': '2',
             'form-INITIAL_FORMS': '2',
             'form-0-id': p0.pk,
             'form-0-slug': 'temp0',
             'form-1-id': p1.pk,
             'form-1-slug': 'temp1',
         }
         formset = FormSet(data)
         self.assertTrue(formset.is_valid())
         formset.save()

         data = {
             'form-TOTAL_FORMS': '2',
             'form-INITIAL_FORMS': '2',
             # Swap slug values.
             'form-0-id': p0.pk,
             'form-0-slug': 'car-blue',
             'form-1-id': p1.pk,
             'form-1-slug': 'car-red',
         }
         formset = FormSet(data)
         self.assertTrue(formset.is_valid())
         formset.save()

         p0 = Product.objects.get(pk=p0.pk)
         self.assertEquals(p0.slug, 'car-blue')
         p1 = Product.objects.get(pk=p1.pk)
         self.assertEquals(p1.slug, 'car-red')
 }}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25139>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.88bce714b3bc49c5cdd2d12506428980%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to