==== Test code
Consider the following code, where the Django Admin provides access to a
'''Groups''' page with a '''Persons''' inline.
models.py:
{{{#!python
from django.db import models
class Group(models.Model):
name = models.CharField(max_length=30)
class Person(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
}}}
admin.py:
{{{#!python
from django.contrib import admin
from .models import *
class PersonInline(admin.StackedInline):
model = Person
extra = 0
@admin.register(Group)
class GroupAdmin(admin.ModelAdmin):
inlines = [PersonInline]
}}}
==== Steps to reproduce
1. Go to the Group add page (for example,
<http://localhost:8000/admin/myapp/group/add/>). Enter a Group name, add a
Person with first_name and last_name, and click '''Save and continue
editing'''.
2. Change the Group name. Add a second Person for the group, but enter a
first_name only. A delete button ({{{X}}} icon) is available to discard
the pending record: [[Image(https://s13.postimg.org/6wv1azzyv/image.png)]]
3. Click '''SAVE'''. There will be a validation error, as expected,
because last_name is not provided. However, the '''Delete''' button is
missing: [[Image(https://s13.postimg.org/3q0hrduyf/image.png)]]
4. '''The user is now forced to either (a) fix the validation error or (b)
reload the page, discarding all unrelated changes on the page. It is not
possible for the user to fix the validation error by simply
canceling/deleting the pending new record.'''
--
Ticket URL: <https://code.djangoproject.com/ticket/29087>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:1>
* status: new => assigned
* owner: nobody => Vitor Freitas
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:2>
* owner: Vitor Freitas => (none)
* status: assigned => new
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:3>
* status: new => assigned
* owner: (none) => frnhr
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:4>
* has_patch: 0 => 1
Comment:
PR: https://github.com/django/django/pull/11504
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:5>
Old description:
New description:
==== Test code
==== Steps to reproduce
----
==== It is actually worse than that...
Another cause of validation errors can be uniqueness constraints. These
errors can be difficult to fix and sometimes actually cannot be fixed. So
it is totally possible that because of a validation error the user is
**forced to reload the page**, there is no other choice.
Building on the models above, here is an example of a validation error
that can be unsalvageable for users without the `create` permission for
groups. New `Council` model is added, a foreign key from `Person` to
`Council` is created and also a constraint with `unique_together =
('council', 'group')` is set.
[[Image(https://i.ibb.co/41gpvgS/Screenshot-2019-08-30-at-21-08-13.png)]]
--
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:6>
Old description:
> When adding a new inline record in the Django Admin, it is impossible to
>
> ----
>
> ==== It is actually worse than that...
>
> Another cause of validation errors can be uniqueness constraints. These
> errors can be difficult to fix and sometimes actually cannot be fixed. So
> it is totally possible that because of a validation error the user is
> **forced to reload the page**, there is no other choice.
>
> Building on the models above, here is an example of a validation error
> that can be unsalvageable for users without the `create` permission for
> groups. New `Council` model is added, a foreign key from `Person` to
> `Council` is created and also a constraint with `unique_together =
> ('council', 'group')` is set.
>
> [[Image(https://i.ibb.co/41gpvgS/Screenshot-2019-08-30-at-21-08-13.png)]]
New description:
==== Test code
==== Steps to reproduce
----
==== It is actually worse than that...
Another cause of validation errors can be uniqueness constraints. These
errors can be difficult to fix and sometimes actually cannot be fixed. So
it is totally possible that because of a validation error the user is
**forced to reload the page**, there is no other choice.
Building on the models above, here is an example of a validation error
that can be unsalvageable for users without the `create` permission for
groups. New `Council` model is added, a foreign key from `Person` to
`Council` is created and also a constraint with `unique_together =
('council', 'group')` is set.
[[Image(https://i.ibb.co/K2ndRGT/Screenshot-2019-08-30-at-21-08-13.png)]]
--
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:7>
* needs_better_patch: 0 => 1
Comment:
Fix should address `TabularInline` too. (This has the same issue.) Also,
the PR includes a significant refactoring, which should be in a separate
commit.
But other than that, looks goods. (Works 🙂)
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:8>
* needs_better_patch: 1 => 0
Comment:
PR edited
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:9>
* stage: Accepted => Ready for checkin
Comment:
PR is ready to go.
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:10>
Comment (by Carlton Gibson <carlton@…>):
In [changeset:"6ea3aadd17f937e69d121e3ae1a415a435e3267d" 6ea3aad]:
{{{
#!CommitTicketReference repository=""
revision="6ea3aadd17f937e69d121e3ae1a415a435e3267d"
Refs #29087 -- Refactored admin inlines.js.
Split logic into separate functions to clarify and allow reuse.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:11>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"24e540fbd71bd2b0843e751bde61ad0052a811b3" 24e540f]:
{{{
#!CommitTicketReference repository=""
revision="24e540fbd71bd2b0843e751bde61ad0052a811b3"
Fixed #29087 -- Added delete buttons for unsaved admin inlines on
validation error.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:12>
Comment (by Carlton Gibson <carlton@…>):
In [changeset:"f4272d000af598018247fe9687dac0fd02a29a7c" f4272d00]:
{{{
#!CommitTicketReference repository=""
revision="f4272d000af598018247fe9687dac0fd02a29a7c"
Fixed #32348, Refs #29087 -- Corrected tutorial for updated deleting
inlines UI.
Updated tutorial to match change in
24e540fbd71bd2b0843e751bde61ad0052a811b3
allowing deletion of original extra inlines.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:13>
Comment (by Carlton Gibson <carlton.gibson@…>):
In [changeset:"4dbbe3747955cbecbf3668c93a0c885562f063ac" 4dbbe37]:
{{{
#!CommitTicketReference repository=""
revision="4dbbe3747955cbecbf3668c93a0c885562f063ac"
[3.2.x] Fixed #32348, Refs #29087 -- Corrected tutorial for updated
deleting inlines UI.
Updated tutorial to match change in
24e540fbd71bd2b0843e751bde61ad0052a811b3
allowing deletion of original extra inlines.
Backport of f4272d000af598018247fe9687dac0fd02a29a7c from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:14>
Comment (by Carlton Gibson <carlton.gibson@…>):
In [changeset:"fa203f17591d53178c28b20f9ad337812666445d" fa203f17]:
{{{
#!CommitTicketReference repository=""
revision="fa203f17591d53178c28b20f9ad337812666445d"
[3.1.x] Fixed #32348, Refs #29087 -- Corrected tutorial for updated
deleting inlines UI.
Updated tutorial to match change in
24e540fbd71bd2b0843e751bde61ad0052a811b3
allowing deletion of original extra inlines.
Backport of f4272d000af598018247fe9687dac0fd02a29a7c from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:15>
* status: closed => new
* resolution: fixed =>
Comment:
This bug still exists in Django 2.22
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:16>
* status: new => closed
* resolution: => fixed
Comment:
Please don't reopen closed tickets.
This fix was made as part of Django 3.1 (see
24e540fbd71bd2b0843e751bde61ad0052a811b3)
You'll need to update to that or beyond.
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:17>
Comment (by Backit):
Replying to [comment:17 Carlton Gibson]:
> Please don't reopen closed tickets.
>
> This fix was made as part of Django 3.1 (see
24e540fbd71bd2b0843e751bde61ad0052a811b3)
> You'll need to update to that or beyond.
But 2.2 is still supported, so should receive bugfixes, isn'it?
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:18>
Comment (by Mariusz Felisiak):
Replying to [comment:18 Backit]:
> But 2.2 is still supported, so should receive bugfixes, isn'it?
Django 2.2. is in extended support so it receives only security patches.
--
Ticket URL: <https://code.djangoproject.com/ticket/29087#comment:19>