1. Luke Plant
  2. django

Commits

adr...@bcc190cf-cafb-0310-a4f2-bffc1f526a37  committed 5d9a715

Fixed #2433 -- Added allow_future option to date-based generic views

  • Participants
  • Parent commits ae60247
  • Branches default

Comments (0)

Files changed (2)

File django/views/generic/date_based.py

View file
 def archive_index(request, queryset, date_field, num_latest=15,
         template_name=None, template_loader=loader,
         extra_context=None, allow_empty=False, context_processors=None,
-        mimetype=None):
+        mimetype=None, allow_future=False):
     """
     Generic top-level archive of date-based objects.
 
     """
     if extra_context is None: extra_context = {}
     model = queryset.model
-    queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
+    if not allow_future:
+        queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
     date_list = queryset.dates(date_field, 'year')[::-1]
     if not date_list and not allow_empty:
         raise Http404, "No %s available" % model._meta.verbose_name
 def archive_year(request, year, queryset, date_field, template_name=None,
         template_loader=loader, extra_context=None, allow_empty=False,
         context_processors=None, template_object_name='object', mimetype=None,
-        make_object_list=False):
+        make_object_list=False, allow_future=False):
     """
     Generic yearly archive view.
 
 
     lookup_kwargs = {'%s__year' % date_field: year}
 
-    # Only bother to check current date if the year isn't in the past.
-    if int(year) >= now.year:
+    # Only bother to check current date if the year isn't in the past and future objects aren't requested.
+    if int(year) >= now.year and not allow_future:
         lookup_kwargs['%s__lte' % date_field] = now
     date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
     if not date_list and not allow_empty:
 def archive_month(request, year, month, queryset, date_field,
         month_format='%b', template_name=None, template_loader=loader,
         extra_context=None, allow_empty=False, context_processors=None,
-        template_object_name='object', mimetype=None):
+        template_object_name='object', mimetype=None, allow_future=False):
     """
     Generic monthly archive view.
 
         last_day = first_day.replace(month=first_day.month + 1)
     lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
 
-    # Only bother to check current date if the month isn't in the past.
-    if last_day >= now.date():
+    # Only bother to check current date if the month isn't in the past and future objects are requested.
+    if last_day >= now.date() and not allow_future:
         lookup_kwargs['%s__lte' % date_field] = now
     object_list = queryset.filter(**lookup_kwargs)
     if not object_list and not allow_empty:
         raise Http404
+
+    # Calculate the next month, if applicable.
+    if allow_future:
+        next_month = last_day + datetime.timedelta(days=1)
+    elif last_day < datetime.date.today():
+        next_month = last_day + datetime.timedelta(days=1)
+    else:
+        next_month = None
+
     if not template_name:
         template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
     c = RequestContext(request, {
         '%s_list' % template_object_name: object_list,
         'month': date,
-        'next_month': (last_day < datetime.date.today()) and (last_day + datetime.timedelta(days=1)) or None,
+        'next_month': next_month,
         'previous_month': first_day - datetime.timedelta(days=1),
     }, context_processors)
     for key, value in extra_context.items():
 def archive_week(request, year, week, queryset, date_field,
         template_name=None, template_loader=loader,
         extra_context=None, allow_empty=True, context_processors=None,
-        template_object_name='object', mimetype=None):
+        template_object_name='object', mimetype=None, allow_future=False):
     """
     Generic weekly archive view.
 
     last_day = date + datetime.timedelta(days=7)
     lookup_kwargs = {'%s__range' % date_field: (first_day, last_day)}
 
-    # Only bother to check current date if the week isn't in the past.
-    if last_day >= now.date():
+    # Only bother to check current date if the week isn't in the past and future objects aren't requested.
+    if last_day >= now.date() and not allow_future:
         lookup_kwargs['%s__lte' % date_field] = now
     object_list = queryset.filter(**lookup_kwargs)
     if not object_list and not allow_empty:
         month_format='%b', day_format='%d', template_name=None,
         template_loader=loader, extra_context=None, allow_empty=False,
         context_processors=None, template_object_name='object',
-        mimetype=None):
+        mimetype=None, allow_future=False):
     """
     Generic daily archive view.
 
         '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
     }
 
-    # Only bother to check current date if the date isn't in the past.
-    if date >= now.date():
+    # Only bother to check current date if the date isn't in the past and future objects aren't requested.
+    if date >= now.date() and not allow_future:
         lookup_kwargs['%s__lte' % date_field] = now
     object_list = queryset.filter(**lookup_kwargs)
     if not allow_empty and not object_list:
         raise Http404
+
+    # Calculate the next day, if applicable.
+    if allow_future:
+        next_day = date + datetime.timedelta(days=1)
+    elif date < datetime.date.today():
+        next_day = date + datetime.timedelta(days=1)
+    else:
+        next_day = None
+
     if not template_name:
         template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
     t = template_loader.get_template(template_name)
         '%s_list' % template_object_name: object_list,
         'day': date,
         'previous_day': date - datetime.timedelta(days=1),
-        'next_day': (date < datetime.date.today()) and (date + datetime.timedelta(days=1)) or None,
+        'next_day': next_day,
     }, context_processors)
     for key, value in extra_context.items():
         if callable(value):
         month_format='%b', day_format='%d', object_id=None, slug=None,
         slug_field=None, template_name=None, template_name_field=None,
         template_loader=loader, extra_context=None, context_processors=None,
-        template_object_name='object', mimetype=None):
+        template_object_name='object', mimetype=None, allow_future=False):
     """
     Generic detail view from year/month/day/slug or year/month/day/id structure.
 
         '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
     }
 
-    # Only bother to check current date if the date isn't in the past.
-    if date >= now.date():
+    # Only bother to check current date if the date isn't in the past and future objects aren't requested.
+    if date >= now.date() and not allow_future:
         lookup_kwargs['%s__lte' % date_field] = now
     if object_id:
         lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id

File docs/generic_views.txt

View file
 **Description:**
 
 A top-level index page showing the "latest" objects, by date. Objects with
-a date in the *future* are not included.
+a date in the *future* are not included unless you set ``allow_future`` to
+``True``.
 
 **Required arguments:**
 
     * ``mimetype``: The MIME type to use for the resulting document. Defaults
       to the value of the ``DEFAULT_MIME_TYPE`` setting.
 
+    * ``allow_future``: A boolean specifying whether to include "future"
+      objects on this page, where "future" means objects in which the field
+      specified in ``date_field`` is greater than the current date/time. By
+      default, this is ``False``.
+
 **Template name:**
 
 If ``template_name`` isn't specified, this view will use the template
 **Description:**
 
 A yearly archive page showing all available months in a given year. Objects
-with a date in the *future* are not displayed.
+with a date in the *future* are not displayed unless you set ``allow_future``
+to ``True``.
 
 **Required arguments:**
 
     * ``mimetype``: The MIME type to use for the resulting document. Defaults
       to the value of the ``DEFAULT_MIME_TYPE`` setting.
 
+    * ``allow_future``: A boolean specifying whether to include "future"
+      objects on this page, where "future" means objects in which the field
+      specified in ``date_field`` is greater than the current date/time. By
+      default, this is ``False``.
+
 **Template name:**
 
 If ``template_name`` isn't specified, this view will use the template
 **Description:**
 
 A monthly archive page showing all objects in a given month. Objects with a
-date in the *future* are not displayed.
+date in the *future* are not displayed unless you set ``allow_future`` to
+``True``.
 
 **Required arguments:**
 
     * ``mimetype``: The MIME type to use for the resulting document. Defaults
       to the value of the ``DEFAULT_MIME_TYPE`` setting.
 
+    * ``allow_future``: A boolean specifying whether to include "future"
+      objects on this page, where "future" means objects in which the field
+      specified in ``date_field`` is greater than the current date/time. By
+      default, this is ``False``.
+
 **Template name:**
 
 If ``template_name`` isn't specified, this view will use the template
 **Description:**
 
 A weekly archive page showing all objects in a given week. Objects with a date
-in the *future* are not displayed.
+in the *future* are not displayed unless you set ``allow_future`` to ``True``.
 
 **Required arguments:**
 
     * ``mimetype``: The MIME type to use for the resulting document. Defaults
       to the value of the ``DEFAULT_MIME_TYPE`` setting.
 
+    * ``allow_future``: A boolean specifying whether to include "future"
+      objects on this page, where "future" means objects in which the field
+      specified in ``date_field`` is greater than the current date/time. By
+      default, this is ``False``.
+
 **Template name:**
 
 If ``template_name`` isn't specified, this view will use the template
 **Description:**
 
 A day archive page showing all objects in a given day. Days in the future throw
-a 404 error, regardless of whether any objects exist for future days.
+a 404 error, regardless of whether any objects exist for future days, unless
+you set ``allow_future`` to ``True``.
 
 **Required arguments:**
 
     * ``mimetype``: The MIME type to use for the resulting document. Defaults
       to the value of the ``DEFAULT_MIME_TYPE`` setting.
 
+    * ``allow_future``: A boolean specifying whether to include "future"
+      objects on this page, where "future" means objects in which the field
+      specified in ``date_field`` is greater than the current date/time. By
+      default, this is ``False``.
+
 **Template name:**
 
 If ``template_name`` isn't specified, this view will use the template
 
 **Description:**
 
-A page representing an individual object.
+A page representing an individual object. If the object has a date value in the
+future, the view will throw a 404 error by default, unless you set
+``allow_future`` to ``True``.
 
 **Required arguments:**
 
     * ``mimetype``: The MIME type to use for the resulting document. Defaults
       to the value of the ``DEFAULT_MIME_TYPE`` setting.
 
+    * ``allow_future``: A boolean specifying whether to include "future"
+      objects on this page, where "future" means objects in which the field
+      specified in ``date_field`` is greater than the current date/time. By
+      default, this is ``False``.
+
 **Template name:**
 
 If ``template_name`` isn't specified, this view will use the template