Fixed #10919 -- Added ModelAdmin option to truncate delete confirmation object list.#20903
Fixed #10919 -- Added ModelAdmin option to truncate delete confirmation object list.#20903rodbv wants to merge 3 commits intodjango:mainfrom
Conversation
There was a problem hiding this comment.
Hello! Thank you for your contribution 💪
As it's your first contribution be sure to check out the patch review checklist.
If you're fixing a ticket from Trac make sure to set the "Has patch" flag and include a link to this PR in the ticket!
If you have any design or process questions then you can ask in the Django forum.
Welcome aboard ⛵️!
f69a687 to
3a4e285
Compare
385d74a to
c670447
Compare
|
nicely done @rodbv 👏 . I like your solution, but I was wondering if instead of having the plain text "...and N more" you could make it into a link that will show the full results. All optional of course, in my opinion as it is already adds value for this use case :) |
Thanks @naranjo-it! I will check both possibilities, I guess that making the "...and N more" text a link that reloads the page with truncation disabled is pretty straightforward and it would ensure users don't lose the ability to check any specific objects if they want to. |
After some checks, it's not that straighforward because one of the ways to get to the confirmation page is via So I will leave the PR as it is by now, to avoid adding too much complexity, and see what else is requested. |
jacobtylerwalls
left a comment
There was a problem hiding this comment.
Thanks for the start here @rodbv, any progress we can make on this problem is going to be very welcomed by folks, I think!
So, my first thought is: I'm assuming an important part of the performance problem is fetching millions of rows from the db, not necessarily just rendering the million <li> rows. Did you look into an approach that would slice the queryset or otherwise limit the collected objects up front?
django/template/defaultfilters.py
Outdated
| def list_formatter(item_list, tabs=1): | ||
| indent = "\t" * tabs | ||
| output = [] | ||
| truncated_count = 0 |
There was a problem hiding this comment.
This counter gets reset on each recursion, so I'm getting n * m related objects for a limit of n and m related models.
There was a problem hiding this comment.
Yes, that's by design, from this perspective: Suppose we have a blog system and we're applying delete_confirmation_max_objects on BlogAdmin, with value 30. From the user's perspective, it means "it want to see at most 30 posts on the confirmation page, and you can truncate the rest". So if there are more than 30 posts, they will consistently see 30 items and then "...and N more".
If we adopt a global counter, and the first post happens to have 100 comments, they would see only 1 post, 29 comments of the first post. If the order of posts change, they may see different numbers of posts.
Having said that I'm not totally against a global counter, if you prefer, I went for the most conservative approach.
There was a problem hiding this comment.
@jacobtylerwalls Now that you showed me the case for mixed types on the same level, I am reconsidering this approach, as it may be hiding some types anyway. Maybe make the counter global and have at the end an outdented message like "N objects not displayed" could be better. What do you think?
There was a problem hiding this comment.
I think this is a great time to go to the forum.
Since new ModelAdmin attributes are only a couple steps lower on the ladder of Debatable Ideas than new settings (😄), and since this ticket was accepted ~17 years ago without a clear statement of "yes, let's add a ModelAdmin attribute", I think it would be good to loop in other voices besides mine.
I would succinctly state:
- why you are focusing on the front-end truncation solution only (I took it to be that even with a backend solution we'd still want to tune the front-end display?)
- the issue with mixed types and how we have to choose between a global counter versus n^max_depth, showing an example of the two possible outputs
Finally, we also need to decide what approach harmonizes best with #20945, which implements a backend limit for a very similar use case.
There was a problem hiding this comment.
Done. I can only post 1 embedded image and 2 links on my post there, as it's my first topic (got an error message when I submitted). So I will upload a preview of the global solution here and link :P
There was a problem hiding this comment.
Thanks! (I think the forum post link to this 404's for me, maybe take another look?)
There was a problem hiding this comment.
Weird 🤔 It's in Django Internals, with title Design feedback: Truncating the related objects list in Admin delete confirmation (Ticket #10919)
There was a problem hiding this comment.
Oh, I just meant the link to the above image at "[you can see an example here]"
My focus on this PR is on the frontend: reduce the amount of data sent to the browser, and the annoyance of scrolling a long way down to reach the "I'm sure" button. For millions of items it will be a problem indeed, but hopefully for most cases (thousands of items) the db performance is not too bad. |
jacobtylerwalls
left a comment
There was a problem hiding this comment.
This looks great! Just a handful of very minor questions for you about wording and such.
| "<li>D</li>", | ||
| ) | ||
|
|
||
| def test_non_iterable_list_subclass(self): |
There was a problem hiding this comment.
Adds test coverage for type error check on _walk_items.
81793f7 to
41aa1e8
Compare
…_unordered_list filter.
…dmin. The new ModelAdmin.delete_confirmation_max_display attribute allows limiting the number of related objects shown on the delete confirmation page. When the limit is reached, a "…and N more." message is shown. The feature relies on a new truncated_unordered_list template filter added to django.contrib.admin.templatetags.admin_filters. Thanks Jacob Tyler Walls for the review, Tobias McNulty for the report, and terminator14 for the solution suggested.
Uncovered lines in changed filesNote: Missing lines are warnings only. Some database-specific lines may not be measured. More information |
Trac ticket number
ticket-10919
Branch description
The original ticket proposed adding an option to limit or hide the list of related objects shown on the delete confirmation page. This list can become very long, especially for complex object graphs, because related items are rendered recursively. As a result, the confirmation button is pushed far down the page.
This PR implements a suggestion by @terminator14 (comment 13) to truncate the list at a given number, which is configurable, and complement the list with
…and N more.The setting is called
delete_confirmation_max_displayand its default value isNone, which means it's an opt-in setting.It renders like this
Dark mode - note that truncation is also applied to nested items
This still gives the user a good sense of the impact of the deletion, but keeps the page size and memory usage within reasonable limits.
AI Assistance Disclosure (REQUIRED)
Used GitHub Copilot to request an initial review, considering the practices found on the codebase, and also to generate HTML for test cases. I fully reviewed and verified all output before submitting this PR. The solution/algorithm is mine.
Checklist
mainbranch.