Get the next or the previous valid date. The idea is to allow links on month/day views to never be 404s by never providing a date that'll be invalid for the given view. This is a bit complicated since it handles different intervals of time, hence the coupling to generic_view.
(generic_view, date, is_previous, period)
| 726 | |
| 727 | |
| 728 | def _get_next_prev(generic_view, date, is_previous, period): |
| 729 | """ |
| 730 | Get the next or the previous valid date. The idea is to allow links on |
| 731 | month/day views to never be 404s by never providing a date that'll be |
| 732 | invalid for the given view. |
| 733 | |
| 734 | This is a bit complicated since it handles different intervals of time, |
| 735 | hence the coupling to generic_view. |
| 736 | |
| 737 | However in essence the logic comes down to: |
| 738 | |
| 739 | * If allow_empty and allow_future are both true, this is easy: just |
| 740 | return the naive result (just the next/previous day/week/month, |
| 741 | regardless of object existence.) |
| 742 | |
| 743 | * If allow_empty is true, allow_future is false, and the naive result |
| 744 | isn't in the future, then return it; otherwise return None. |
| 745 | |
| 746 | * If allow_empty is false and allow_future is true, return the next |
| 747 | date *that contains a valid object*, even if it's in the future. If |
| 748 | there are no next objects, return None. |
| 749 | |
| 750 | * If allow_empty is false and allow_future is false, return the next |
| 751 | date that contains a valid object. If that date is in the future, or |
| 752 | if there are no next objects, return None. |
| 753 | """ |
| 754 | date_field = generic_view.get_date_field() |
| 755 | allow_empty = generic_view.get_allow_empty() |
| 756 | allow_future = generic_view.get_allow_future() |
| 757 | |
| 758 | get_current = getattr(generic_view, "_get_current_%s" % period) |
| 759 | get_next = getattr(generic_view, "_get_next_%s" % period) |
| 760 | |
| 761 | # Bounds of the current interval |
| 762 | start, end = get_current(date), get_next(date) |
| 763 | |
| 764 | # If allow_empty is True, the naive result will be valid |
| 765 | if allow_empty: |
| 766 | if is_previous: |
| 767 | result = get_current(start - datetime.timedelta(days=1)) |
| 768 | else: |
| 769 | result = end |
| 770 | |
| 771 | if allow_future or result <= timezone_today(): |
| 772 | return result |
| 773 | else: |
| 774 | return None |
| 775 | |
| 776 | # Otherwise, we'll need to go to the database to look for an object |
| 777 | # whose date_field is at least (greater than/less than) the given |
| 778 | # naive result |
| 779 | else: |
| 780 | # Construct a lookup and an ordering depending on whether we're doing |
| 781 | # a previous date or a next date lookup. |
| 782 | if is_previous: |
| 783 | lookup = {"%s__lt" % date_field: generic_view._make_date_lookup_arg(start)} |
| 784 | ordering = "-%s" % date_field |
| 785 | else: |
no test coverage detected