We saw an unexpected result working with model formsets and recently stale 
data. 

Consider a simple Book model with soft deletion.

```
class Book(models.Model):
    name = models.CharField(max_length=100)
    deleted = models.BooleanField(default=False)
```

We have one book

```
book = Book.objects.create(name="Grapes of Wrath")
```

and a model formset to edit Books.

```
BookFormSet = modelformset_factory(Book, fields=('name',), max_num=None, 
extra=0)
```

A user initializes a formset to edit all non-deleted books. While that user 
is filling out the edit form, another user deletes the book.

```
# The user calls a view that initializes the formset. 
formset = BookFormSet(queryset=Book.objects.filter(deleted=False))
data = {
            'form-TOTAL_FORMS': '1',
            'form-INITIAL_FORMS': '1',
            'form-MAX_NUM_FORMS': '',
            'form-0-id': book.pk,
            'form-0-name': "New Title"
    }

# Before submission, another user deletes the book. 
book.deleted = True
book.save()

# Now the original user submits the form
formset = BookFormSet(data=data, 
queryset=Book.objects.filter(deleted=False))
formset.is_valid()  # True
formset.save()
```

Two Books now exist. Despite having `data['form-0-id'] = book.pk` and 
extra=0, django uses a ModelForm with instance=None, which ends up creating 
a new row. This is because BaseModelFormSet's _existing_object returns None 
if the submitted id is not in the queryset's set of ids. 
https://github.com/django/django/blob/master/django/forms/models.py#L573. 

Is this expected? If an id is submitted with a form, and that id isn't 
expected, could it make sense for formset validation to fail instead? 







-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/67d21f43-1da8-49af-8ad3-95042628fac6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to