Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#25919 closed Bug (duplicate)

Wrong behavior after saving on changelist page when any field is list_editable

Reported by: Alex Owned by: nobody
Component: contrib.admin Version: 1.9
Severity: Normal Keywords: list_editable pagination cl.result_list queryset
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Assume there is a simple model

class SomeModel(models.Model):
    name = models.CharField('name', max_length=64)

and simple admin for it (note 2 items per page and in-line editable field "name")

@admin.register(SomeModel)
class SomeModelAdmin(admin.ModelAdmin):
    list_display = ['id' ,'name']
    list_editable = ['name']
    list_per_page = 2

Go to admin page and create two instances of SomeModel with names, say, "alpha" and "beta". Then, open the same admin page (/admin/testapp/somemodel/) in another browser tab and create another instance ("gamma"). Return to the first tab (it's of course unchanged and there still remain "alpha" and "beta" instances) and change in-line field "name" from "alpha" to "lambda" and press "save". Then press "show all" and you'll see that you haven't changed "alpha" to "lambda" - you created new instance "lambda", and "alpha" also remains there!

The source of this bug is in django/contrib/admin/options.py :

    # Handle POSTed bulk-edit data.
    if (request.method == "POST" and cl.list_editable and
            '_save' in request.POST and not action_failed):
        FormSet = self.get_changelist_formset(request)
        formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list)

When user clicks "save", the page sends correct POST data like this:

"form-0-id" = "0",
"form-0-name" = "beta",
"form-1-id" = "1",
"form-1-name" = "lambda"  <-- was "alpha" before

But there is code ( queryset=cl.result_list ) which restricts form's instances to those that are on current admin page ( /admin/testapp/somemodel/ ). As you remember, we have 3 instances - "alpha", "beta", "gamma", and according to list_per_page = 2 only last two instances are shown - these are "beta" and "gamma".

When the form's POST data ("beta", "alpha -> lambda") fits instances from queryset ("beta", "gamma"), it finds "beta" and changes it without errors, but it cannot find "alpha" and change it - so it thinks that we added new record and creates an instance with value "lambda". This is not a desired behavior.

Removing the queryset restriction solves this problem. I am wondering whether that queryset was there at all.

Attachments (2)

diff.txt (187 bytes) - added by Alex 4 years ago.
project.tar.gz (9.1 KB) - added by Alex 4 years ago.
Sample project for quick testing (sqlite)

Download all attachments as: .zip

Change History (5)

Changed 4 years ago by Alex

Attachment: diff.txt added

Changed 4 years ago by Alex

Attachment: project.tar.gz added

Sample project for quick testing (sqlite)

comment:1 Changed 4 years ago by Alex

Keywords: list_editable pagination cl.result_list queryset added

comment:2 Changed 4 years ago by Tim Graham

Resolution: duplicate
Status: newclosed

Duplicate of #11313. Could you test the pull request?

comment:3 Changed 4 years ago by Alex

I've investigated. It was because I didn't set up ordering like ordering = ['-id'] . The ordering was undefined for each page slice which led to these kind of errors.

Note: See TracTickets for help on using tickets.
Back to Top