Opened 10 years ago

Last modified 9 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 Aymeric Augustin)

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 Aymeric Augustin, 10 years ago

Description: modified (diff)
Triage Stage: UnreviewedAccepted

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.

comment:2 by Matthias Kestenholz, 9 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.)

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