#9493 closed (fixed)
Formsets with data that violates unique constraints across forms are not marked invalid
Reported by: | Alex Gaynor | Owned by: | Alex Gaynor |
---|---|---|---|
Component: | Forms | Version: | 1.0 |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
If I have a form with a unique name
field, and I submit data that is a dupe of something in the db, it fails validation, however if I have a formset and I submit the same data 2x in the same formset, it passes validation and fails at the save level.
Attachments (14)
Change History (30)
comment:1 by , 16 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Summary: | Formsets with data that violates unique constraints across forms are not mared invalid → Formsets with data that violates unique constraints across forms are not marked invalid |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 16 years ago
by , 16 years ago
Attachment: | formset-unique.3.diff added |
---|
made it a little more effiecient and add docs
comment:3 by , 16 years ago
Thanks to you both for working on this!
I've attached an updated patch with the following minor changes -- sorry for the nitpicking, the patch looks generally good and works well. Also, note that the updated patch has been tested (both by running the testcase and in admin).
1
Why do we need to copy the list on line 943 of the patch
unique_together = self.forms[0].instance._meta.unique_together[:]
and discard it right afterwards (by reusing the unique_together
variable name on next line)? Wouldn't
unique_together = [check for check in self.forms[0].instance._meta.unique_together if [True for field in check if field in self.forms[0].fields]]
be more appropriate?
2
Similarly, wouldn't it make sense to avoid using the bad_fields
intermediary and use errors
directly instead?
3
If there is only one field (i.e. it is a unique, not unique together test), it probably makes sense to call force_unicode
(or indeed, just unicode
) directly instead of get_text_list
:
if len(unique_check) == 1: errors.append(_(u"You have entered duplicate data for %(field)s, all %(field)ss should be unique." % { 'field': force_unicode(field), }))
4
I'd say creating tuple([form.cleaned_data[field] for field in unique_check])
twice in if tuple([form.cleaned_data[field] for field in unique_check]) in data: ... else: data.add(tuple([form.cleaned_data[field] for field in unique_check]))
should be avoided.
comment:4 by , 16 years ago
1) The reason for this is it leads to long and unruly lines, I think this makes it a tad easier to follow.
2) Yes, this can be done, I don't think there is much of a speed difference, and I do think it's easier to read the other way. But however(FWIW this is how it's done for ModelForms as well).
3) Yeah, that should be changed, you need to do field[0] though, as field itself is a tuple.
4) Yes.
comment:5 by , 16 years ago
Alex, if you have time please take a look at the attached patch and improve it further if you see something worth amending (it looks final-ish to me).
(As for The reason for this is it leads to long and unruly lines, I think this makes it a tad easier to follow, I mainly had in main avoiding copying (i.e. foo = a_list
instead of foo = a_list[:]
. Copying is usually required if the local copy is modified -- but not in this case.)
comment:6 by , 16 years ago
3) Yeah, that should be changed, you need to do field[0] though, as field itself is a tuple. -- field
is a field from unique_check
(a tuple), not unique_checks
(a list of tuples), thus not a . The patch has a bit different structure, although your idea remains exactly the same.
by , 16 years ago
Attachment: | formset-unique.4.diff added |
---|
comment:8 by , 16 years ago
Owner: | changed from | to
---|---|
Status: | assigned → new |
by , 16 years ago
Attachment: | formset-unique.5.diff added |
---|
by , 16 years ago
Attachment: | formset-unique.6.diff added |
---|
comment:9 by , 16 years ago
Has patch: | set |
---|---|
milestone: | → 1.1 |
It's a bug in both 1.0 and 1.1, marking as such.
by , 16 years ago
Attachment: | formset-unique.7.diff added |
---|
by , 16 years ago
Attachment: | formset-unique.8.diff added |
---|
comment:10 by , 16 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
by , 16 years ago
Attachment: | formset-unique.9.diff added |
---|
comment:12 by , 16 years ago
Patch needs improvement: | set |
---|---|
Triage Stage: | Ready for checkin → Accepted |
On the whole, this patch looks good. However, I have two comments:
- The patch needs to be updated to include the formset analog of #10134/[10646] (avoiding duplication of logic, if possible).
- While this patch correctly catches the error condition, I'm not satisfied with the way the error is reported. Consider the use case where you have 100 inline forms - a top level "There's a duplicate" error doesn't really help identify the pair of forms that is actually causing the problem. In addition to the formset level error, the individual forms should be marked as being in error.
by , 16 years ago
Attachment: | formset-unique.10.diff added |
---|
added the date stuff and removed code duplication. Not sure what to do to make the formset errors more user friendly. Also needs tests in the worst way (I'll do this during the EDC sprint in all likelyhood)
by , 16 years ago
Attachment: | formset-unique.11.diff added |
---|
by , 16 years ago
Attachment: | formset-unique.12.diff added |
---|
by , 16 years ago
Attachment: | formset-unique.13.diff added |
---|
comment:13 by , 16 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:14 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
#8882 was really the original problem, but since that ticket grew a bit too big, lets use this ticket to track this individual problem.