Opened 33 hours ago

Last modified 4 hours ago

#36067 assigned Cleanup/optimization

Ambiguity of the 'DELETE' text when a TabularInline object does not exist

Reported by: Antoliny Owned by: Antoliny
Component: contrib.admin Version: dev
Severity: Normal Keywords: TabularInline
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When using a foreign key reverse reference model with TabularInline in ModelAdmin, if the corresponding object does not exist, the 'DELETE' text seems unnecessary.
I feel that the 'DELETE' text helps users remove an object when the TabularInline object exists.
However, if the object doesn't exist, the 'DELETE' text seems to lose its purpose.

Attachments (1)

tabular_inline_ex.png (89.0 KB ) - added by Antoliny 33 hours ago.

Download all attachments as: .zip

Change History (5)

by Antoliny, 33 hours ago

Attachment: tabular_inline_ex.png added

comment:1 by Antoliny, 33 hours ago

Owner: set to Antoliny
Status: newassigned

comment:2 by Natalia Bidart, 32 hours ago

Triage Stage: UnreviewedAccepted
Version: 5.1dev

Hello Antoliny, thank you for taking the time to create this report! I agree with you, the "Delete?" legend is confusing and unnecessary.

comment:3 by Antoliny, 13 hours ago

I explored several approaches to address this issue.
I initially wanted to solve it using conditions directly in the template, but there was no suitable attribute available to determine whether each Formset contains objects.

As a solution, I decided to add a self.has_object attribute to the InlineAdminFormSet, assigning it the return value of self.formset.get_queryset().exists(). This allows the presence of the "DELETE?" text to be determined based on whether objects exist.

However, the downside of this approach is that an attribute is being added solely for the purpose of removing the "DELETE?" text. If you have a better suggestion, I would greatly appreciate your advice.

  • django/contrib/admin/helpers.py

    diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
    index 51450d1d9e..97a9f764f1 100644
    a b class InlineAdminFormSet:  
    337337        self.has_change_permission = has_change_permission
    338338        self.has_delete_permission = has_delete_permission
    339339        self.has_view_permission = has_view_permission
     340        self.has_object = self.formset.get_queryset().exists()
    340341
    341342    def __iter__(self):
    342343        if self.has_change_permission:
  • django/contrib/admin/templates/admin/edit_inline/tabular.html

    diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html
    index 7acfda7bd1..e1c7d993b5 100644
    a b  
    2323       {% if field.help_text %}<img src="{% static "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}">{% endif %}
    2424       </th>
    2525     {% endfor %}
    26      {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}<th>{% translate "Delete?" %}</th>{% endif %}
     26     {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission and inline_admin_formset.has_object %}<th>{% translate "Delete?" %}</th>{% endif %}
    2727     </tr></thead>
    2828
    2929     <tbody>

in reply to:  3 comment:4 by Natalia Bidart, 4 hours ago

Replying to Antoliny:

As a solution, I decided to add a self.has_object attribute to the InlineAdminFormSet, assigning it the return value of self.formset.get_queryset().exists(). This allows the presence of the "DELETE?" text to be determined based on whether objects exist.

However, the downside of this approach is that an attribute is being added solely for the purpose of removing the "DELETE?" text. If you have a better suggestion, I would greatly appreciate your advice.

I share your concern with your initial diff. There is one extra query being issued which feels unnecessary. I played a bit with this and settled on having something like this, which nicely reduces logic in the template for calculating the header and checkbox row, and it also uses the existing information in the formset:

  • django/contrib/admin/helpers.py

    diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
    index 51450d1d9e..3e33855394 100644
    a b class InlineAdminFormSet:  
    460460    def total_form_count(self):
    461461        return self.formset.total_form_count
    462462
     463    @property
     464    def can_delete(self):
     465        return (
     466            self.formset.can_delete
     467            and self.has_delete_permission
     468            and any(inlineadminform.original is not None for inlineadminform in self)
     469        )
     470
    463471    @property
    464472    def media(self):
    465473        media = self.opts.media + self.formset.media
  • django/contrib/admin/templates/admin/edit_inline/tabular.html

    diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html
    index 7acfda7bd1..ebbe3dfe25 100644
    a b  
    2323       {% if field.help_text %}<img src="{% static "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}">{% endif %}
    2424       </th>
    2525     {% endfor %}
    26      {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}<th>{% translate "Delete?" %}</th>{% endif %}
     26     {% if inline_admin_formset.can_delete %}<th>{% translate "Delete?" %}</th>{% endif %}
    2727     </tr></thead>
    2828
    2929     <tbody>
     
    5858            {% endfor %}
    5959          {% endfor %}
    6060        {% endfor %}
    61         {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}
     61        {% if inline_admin_formset.can_delete %}
    6262          <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
    6363        {% endif %}
    6464        </tr>

Antoliny, what do you think? This would need a few tests added to existing admin suite.

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