GSoC Task 7 -- Allow swapping of model's pk values

About the Task

What is task represent is that, not always you should blindly follow what a ticket request, you should always have a critical mindset.
The ticket requested to have a functionality where the user should be able to swap unique values (pk) in an HTML form backed by a ModelFormSet. Essentially this means that whenever there is a POST request coming in and has_changed() returned true we will need to check if there were any similar models to last time with only pk’s swapped.

What I did ??

This idea didn’t resonate with me quite well at first. I thought of different ways of approaching this problem, but at the end, we will need to do n(n -1)/2 comparision every time we call save and if there were some changes in the formset. I raised this concerned on the forum. And it turns out it was a very valid argument. And the ticket was marked as Someday/Maybe. Lesson learned: Never blindly follow whatever you see no matter how good it may seem.

Technical description of the task

The reporter of this ticket provided this test which will help us to understand the problem:

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')

Here the function will throw an error at the is_valid() method saying that “Product with this Slug already exists.” The request was to allow such kind of POST request where pk of few elements are swapped.

References

Ticket – #25139