Opened 11 years ago
Last modified 10 years ago
#22536 new Bug
Exceptions using date-based generic views with MySQL, USE_TZ=True and bad data
Reported by: | Chris Adams | Owned by: | Chris Adams |
---|---|---|---|
Component: | Generic views | Version: | 1.5 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I ran into a non-obvious exception while using the date-based generic views. get_previous_day / get_next_day were raising an AttributeError ('NoneType' object has no attribute 'astimezone') in the following code when the view was called with the earliest item in the system:
try: result = getattr(qs[0], date_field) except IndexError: return None # Convert datetimes to dates in the current time zone. if generic_view.uses_datetime_field: if settings.USE_TZ: result = timezone.localtime(result) result = result.date()
This error wasn't immediately obvious because the query shouldn't have been able to return a NULL. Looking at the data revealed the problem: a small number of records on my test instance had invalid dates in MySQL (0000-00-00) which were included by the lt query but subsequently converted into None by the ORM.
The nature of the bug suggests that the cleanest patch might simply be an immediate "if not result: return None", perhaps with a warning about invalid data.
Change History (2)
comment:1 by , 11 years ago
Description: | modified (diff) |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 10 years ago
If we want to be nice there's another case which could be handled here. I just lost hours to debugging a crash which happened because result
was a naive datetime. This was probably the result of a conversion of MySQL to PostgreSQL done without the help of Django, because (as the documentation says) Django always created datetime fields with timezones.
A thing which would have helped me would have been an error message along the lines of "Time zone missing on %(result)s. Your database is broken."
The error message for later reference: ValueError: astimezone() cannot be applied to a naive datetime
.
(At least this comment might point someone else in the correct direction.)
We discussed this ticket on IRC. I believe it's an acceptable solution, provided there's an adequate comment and a MySQL-specific test. The code isn't complex, so this change is low risk.