New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better surfacing of validation errors in UI / optional model instance validation #852
Better surfacing of validation errors in UI / optional model instance validation #852
Conversation
…, and added some helper methods to facilitate meaningful retrieval of that data
…ed a docstring to has_errors() to help differentiate between the two methods
…toggled on or off
…ly) taking care of validation for each row
…ject's 'import_type' attribute to this if validation errors are detected
…d `validate_unique`, which are passed on to instance.full_clean() as `exclude` and `validate_unique`.
…e() method, and conditionally do a few things, depending on the result.
…t has validation errors
…lid rows to be counted
So, I've just realised the app has it's own layer of validation (powered by widgets), which is a little at odds with this approach. I'm certain there are use cases where It feels like we need a way to combine the validation errors from both methods somehow, so that they can be displayed in a similar manner. Any thoughts on this? |
@ababic I've not had a chance to look at this much (and won't for a few days) but I'm excited by this work you're doing! I think this is great. I've definitely had use for seeing both types of errors surfaced better. |
…s and reraise them as a single ValidationError (like django.db.models.Model.clean_fields() does)
…d it to focus purely on combining and raising a ValidationError when appropriate
Okay, I've now got the field and model validation error handling playing nicely together, like I wanted. However, there are a few other things I was wondering about:
|
…ing the diff class for skipped or invalid rows (duh!)
…', as some level of validation always happens, regardless of the option value - it's the use of instance.full_clean() that differs
…or skipped or invalid rows... we'll figure it out later
@ababic in
Here is commit that passes test: Does this makes sense? |
Thanks for looking at it @bmihelac. That is a surprise - even without
And re-raise it (along with other field errors for that row) as a ValidationError. Something I can't yet explain yet is going on here. I'll investigate some more. |
…e version with the widget override to AuthorResourceWithCustomWidget, just overriding the 'name' field.
…et's recreate the original method behaviour.
@bmihelac Okay - now we're cooking :) Python 2 tests are failing as expected - which will no doubt be due to a UnicodeDecodeError being raised. Now we can apply the |
Test suite wise, I'm thinking we should cover the following:
@bmihelac Can you think of anything else? |
@ababic this sounds great |
Okay, cool. I won't get chance to finish things up this weekend due to other commitments, but I'll get this done in the next week or two (max). |
Cool, let me know if anything is needed from me. |
…tely and together
…e, and better handle situations where the ValidationError has 'error_list' but not 'error_dict'
…an error_dict, as we're only interested in the messages at this point
Hi @bmihelac, I'm now happy with these changes :) |
@ababic great news, I'll check it ASAP. Many thanks for your work and patience :) |
@bmihelac Thank you. You too :) |
@@ -269,6 +276,31 @@ def get_or_init_instance(self, instance_loader, row): | |||
else: | |||
return (self.init_instance(row), True) | |||
|
|||
def validate_instance(self, instance, import_validation_errors={}, validate_unique=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def validate_instance(self, instance, import_validation_errors=None, validate_unique=True):
if import_validation_errors is None:
errors = {}
else:
erros = import_validation_errors.copy()
Suggestion - using None instead of mutable dict
.
As per https://docs.quantifiedcode.com/python-anti-patterns/correctness/mutable_default_value_as_argument.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bmihelac Fully agree - that's a better solution :)
I'm testing this feature and it's not catching a DoesNotExist exception. Model:
Resource:
Test:
|
Hi @edgabaldi. If |
Hi @bmihelac,
Related issues:
Here's where I've got to so far. I thought it would be good to get some feedback before getting stuck into writing new tests, but the current ones are passing, so at least nothing is broken :)
When enabled,
instance.full_clean()
is called for each row, and any resulting validation errors surface themselves in the preview table like so:The errors are hidden visually at first, then become visible when you hover over a row's first column, in such a way that it doesn't hide any of the values for the current row. It's pretty crude, but it's a starting point. Some examples:
Anyone wanting to give this a whirl for themselves should be able to install from git using:
pip install git+https://github.com/ababic/django-import-export.git@modelresource-validation-error-handling
Any/all feedback welcome :)