U
    [+df                     @   s  d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d d	lmZ d d
lmZmZ d dlmZmZ G dd dZG dd dZG dd dZG dd dZG dd dZG dd deeeZG dd deZG dd deeZG dd deeZ G dd dee Z!G d d! d!eeeZ"G d"d# d#ee"Z#G d$d% d%eeeZ$G d&d' d'ee$Z%G d(d) d)eeeeZ&G d*d+ d+ee&Z'G d,d- d-e&Z(G d.d/ d/ee(Z)G d0d1 d1eeeeeZ*G d2d3 d3ee*Z+d<d6d7Z,d8d9 Z-d:d; Z.dS )=    N)settings)ImproperlyConfigured)models)Http404)timezone)cached_property)gettext)View)BaseDetailView!SingleObjectTemplateResponseMixin)MultipleObjectMixin#MultipleObjectTemplateResponseMixinc                   @   sH   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dd ZdS )	YearMixinz-Mixin for views manipulating year-based data.z%YNc                 C   s   | j S )zv
        Get a year format string in strptime syntax to be used to parse the
        year from url variables.
        )year_formatself r   >/tmp/pip-unpacked-wheel-n7e__lmp/django/views/generic/dates.pyget_year_format   s    zYearMixin.get_year_formatc                 C   sh   | j }|dkrdz| jd }W nF tk
rb   z| jjd }W n  tk
r\   ttdY nX Y nX |S )z8Return the year for which this view should display data.NyearzNo year specified)r   kwargsKeyErrorrequestGETr   _)r   r   r   r   r   get_year"   s    zYearMixin.get_yearc                 C   s   t | |dddS )zGet the next valid year.Fr   is_previousperiod_get_next_prevr   dater   r   r   get_next_year/   s    zYearMixin.get_next_yearc                 C   s   t | |dddS )zGet the previous valid year.Tr   r   r   r!   r   r   r   get_previous_year3   s    zYearMixin.get_previous_yearc                 C   s>   z|j |jd dddW S  tk
r8   ttdY nX dS )
        Return the start date of the next interval.

        The interval is defined by start date <= item date < next start date.
           r   monthdayDate out of rangeN)replacer   
ValueErrorr   r   r!   r   r   r   _get_next_year7   s    zYearMixin._get_next_yearc                 C   s   |j dddS ).Return the start date of the current interval.r&   r(   r)   r+   r!   r   r   r   _get_current_yearB   s    zYearMixin._get_current_year)__name__
__module____qualname____doc__r   r   r   r   r#   r$   r-   r1   r   r   r   r   r      s   r   c                   @   sH   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dd ZdS )
MonthMixinz.Mixin for views manipulating month-based data.z%bNc                 C   s   | j S )zx
        Get a month format string in strptime syntax to be used to parse the
        month from url variables.
        )month_formatr   r   r   r   get_month_formatM   s    zMonthMixin.get_month_formatc                 C   sh   | j }|dkrdz| jd }W nF tk
rb   z| jjd }W n  tk
r\   ttdY nX Y nX |S )z9Return the month for which this view should display data.Nr(   zNo month specified)r(   r   r   r   r   r   r   )r   r(   r   r   r   	get_monthT   s    zMonthMixin.get_monthc                 C   s   t | |dddS )zGet the next valid month.Fr(   r   r   r!   r   r   r   get_next_montha   s    zMonthMixin.get_next_monthc                 C   s   t | |dddS )zGet the previous valid month.Tr(   r   r   r!   r   r   r   get_previous_monthe   s    zMonthMixin.get_previous_monthc                 C   s^   |j dkrFz|j|jd dddW S  tk
rB   ttdY qZX n|j|j d ddS dS )r%      r&   r'   r*   r/   N)r(   r+   r   r,   r   r   r!   r   r   r   _get_next_monthi   s    
zMonthMixin._get_next_monthc                 C   s   |j ddS )z/Return the start date of the previous interval.r&   )r)   r0   r!   r   r   r   _get_current_monthw   s    zMonthMixin._get_current_month)r2   r3   r4   r5   r7   r(   r8   r9   r:   r;   r=   r>   r   r   r   r   r6   G   s   r6   c                   @   sH   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dd ZdS )DayMixinz,Mixin for views manipulating day-based data.z%dNc                 C   s   | j S )zt
        Get a day format string in strptime syntax to be used to parse the day
        from url variables.
        )
day_formatr   r   r   r   get_day_format   s    zDayMixin.get_day_formatc                 C   sh   | j }|dkrdz| jd }W nF tk
rb   z| jjd }W n  tk
r\   ttdY nX Y nX |S )z7Return the day for which this view should display data.Nr)   zNo day specified)r)   r   r   r   r   r   r   )r   r)   r   r   r   get_day   s    zDayMixin.get_dayc                 C   s   t | |dddS )zGet the next valid day.Fr)   r   r   r!   r   r   r   get_next_day   s    zDayMixin.get_next_dayc                 C   s   t | |dddS )zGet the previous valid day.Tr)   r   r   r!   r   r   r   get_previous_day   s    zDayMixin.get_previous_dayc                 C   s   |t jdd S )r%   r&   days)datetime	timedeltar!   r   r   r   _get_next_day   s    zDayMixin._get_next_dayc                 C   s   |S r.   r   r!   r   r   r   _get_current_day   s    zDayMixin._get_current_day)r2   r3   r4   r5   r@   r)   rA   rB   rC   rD   rI   rK   r   r   r   r   r?   |   s   r?   c                   @   sP   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dd Zdd ZdS )	WeekMixinz-Mixin for views manipulating week-based data.%UNc                 C   s   | j S )zv
        Get a week format string in strptime syntax to be used to parse the
        week from url variables.
        )week_formatr   r   r   r   get_week_format   s    zWeekMixin.get_week_formatc                 C   sh   | j }|dkrdz| jd }W nF tk
rb   z| jjd }W n  tk
r\   ttdY nX Y nX |S )z8Return the week for which this view should display data.NweekzNo week specified)rP   r   r   r   r   r   r   )r   rP   r   r   r   get_week   s    zWeekMixin.get_weekc                 C   s   t | |dddS )zGet the next valid week.FrP   r   r   r!   r   r   r   get_next_week   s    zWeekMixin.get_next_weekc                 C   s   t | |dddS )zGet the previous valid week.TrP   r   r   r!   r   r   r   get_previous_week   s    zWeekMixin.get_previous_weekc                 C   sB   z|t jd| | d W S  tk
r<   ttdY nX dS )r%      rE   r*   N)rG   rH   _get_weekdayOverflowErrorr   r   r!   r   r   r   _get_next_week   s    zWeekMixin._get_next_weekc                 C   s   |t | | S rJ   )rG   rH   rU   r!   r   r   r   _get_current_week   s    zWeekMixin._get_current_weekc                 C   s@   |   }|dkr| S |dkr0| d d S td| dS )z
        Return the weekday for a given date.

        The first day according to the week format is 0 and the last day is 6.
        >   %W%VrM   r&   rT   zunknown week format: %sN)rO   weekdayr,   )r   r"   rN   r   r   r   rU      s    zWeekMixin._get_weekday)r2   r3   r4   r5   rN   rP   rO   rQ   rR   rS   rW   rX   rU   r   r   r   r   rL      s   rL   c                   @   sD   e Zd ZdZdZdZdd Zdd Zedd	 Z	d
d Z
dd ZdS )	DateMixinz3Mixin class for views manipulating date-based data.NFc                 C   s    | j dkrtd| jj | j S )z7Get the name of the date field to be used to filter by.Nz%s.date_field is required.)
date_fieldr   	__class__r2   r   r   r   r   get_date_field   s
    

zDateMixin.get_date_fieldc                 C   s   | j S )zi
        Return `True` if the view should be allowed to display objects from
        the future.
        )allow_futurer   r   r   r   get_allow_future   s    zDateMixin.get_allow_futurec                 C   s6   | j dkr|  j n| j }|j|  }t|tjS )zq
        Return `True` if the date field is a `DateTimeField` and `False`
        if it's a `DateField`.
        N)modelget_queryset_meta	get_fieldr_   
isinstancer   ZDateTimeField)r   rb   fieldr   r   r   uses_datetime_field  s    zDateMixin.uses_datetime_fieldc                 C   s,   | j r(tj|tjj}tjr(t|}|S )z
        Convert a date into a datetime when the date field is a DateTimeField.

        When time zone support is enabled, `date` is assumed to be in the
        current time zone, so that displayed items are consistent with the URL.
        )	rh   rG   combinetimeminr   USE_TZr   Z
make_aware)r   valuer   r   r   _make_date_lookup_arg  s
    
zDateMixin._make_date_lookup_argc                 C   sN   |   }| jrB| |}| |tjdd }d| |d| |iS ||iS dS )z
        Get the lookup kwargs for filtering on a single date.

        If the date field is a DateTimeField, we can't just filter on
        date_field=date because that doesn't take the time into account.
        r&   rE   %s__gte%s__ltN)r_   rh   rn   rG   rH   )r   r"   r]   sinceuntilr   r   r   _make_single_date_lookup  s    
  z"DateMixin._make_single_date_lookup)r2   r3   r4   r5   r]   r`   r_   ra   r   rh   rn   rs   r   r   r   r   r\      s   

	r\   c                   @   sJ   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dddZdS )BaseDateListViewzFAbstract base class for date-based views displaying a list of objects.Fr   c                 O   s6   |   \| _| _}| jf | j| jd|}| |S )N)object_list	date_list)get_dated_itemsrv   ru   Zget_context_dataZrender_to_response)r   r   argsr   Zextra_contextcontextr   r   r   get4  s     zBaseDateListView.getc                 C   s   t ddS )z#Obtain the list of dates and items.z>A DateView must provide an implementation of get_dated_items()N)NotImplementedErrorr   r   r   r   rw   ;  s    z BaseDateListView.get_dated_itemsc                 C   s   | j dkrd|   S | j S )zu
        Return the field or fields to use for ordering the queryset; use the
        date field by default.
        N-%s)orderingr_   r   r   r   r   get_orderingA  s    zBaseDateListView.get_orderingc           	      K   s   |   jf |}|  }|  }|  }| |}|s^| jrDt nt	 }|jf d| |i}|s|dkrp| n|
  }|rttdd|jjji |S )zs
        Get a queryset properly filtered according to `allow_future` and any
        extra lookup kwargs.
        %s__lteN$No %(verbose_name_plural)s availableverbose_name_plural)rc   filterr_   ra   get_allow_emptyZget_paginate_byrh   r   nowtimezone_todayexistsr   r   rb   rd   r   )	r   lookupqsr]   r`   allow_emptyZpaginate_byr   Zis_emptyr   r   r   get_dated_querysetH  s&    
 z#BaseDateListView.get_dated_querysetc                 C   s   | j S )zf
        Get the aggregation period for the list of dates: 'year', 'month', or
        'day'.
        )date_list_periodr   r   r   r   get_date_list_periode  s    z%BaseDateListView.get_date_list_periodNASCc                 C   sr   |   }|  }|dkr |  }| jr6||||}n||||}|dk	rn|sn|snttdd|jj	j
i |S )z
        Get a date list by calling `queryset.dates/datetimes()`, checking
        along the way for empty lists that aren't allowed.
        Nr   r   )r_   r   r   rh   Z	datetimesdatesr   r   rb   rd   r   )r   querysetZ	date_typer}   r]   r   rv   r   r   r   get_date_listl  s      zBaseDateListView.get_date_list)Nr   )r2   r3   r4   r5   r   r   rz   rw   r~   r   r   r   r   r   r   r   rt   .  s   rt   c                   @   s   e Zd ZdZdZdd ZdS )BaseArchiveIndexViewzQ
    Base class for archives of date-based items. Requires a response mixin.
    Zlatestc                 C   s,   |   }| j|dd}|s"| }||i fS ):Return (date_list, items, extra_context) for this request.ZDESC)r}   )r   r   none)r   r   rv   r   r   r   rw     s
    z$BaseArchiveIndexView.get_dated_itemsN)r2   r3   r4   r5   Zcontext_object_namerw   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdZdS )ArchiveIndexViewz&Top-level archive of date-based items.Z_archiveNr2   r3   r4   r5   Ztemplate_name_suffixr   r   r   r   r     s   r   c                   @   s(   e Zd ZdZdZdZdd Zdd ZdS )	BaseYearArchiveView*List of objects published in a given year.r(   Fc           	      C   s   |   }|  }t||  }| |}| | |}d| |d| |i}| jf |}| |}|  sr|	 }|||| 
|| |dfS )r   ro   rp   )r   Z	next_yearZprevious_year)r   r_   _date_from_stringr   rn   r-   r   r   get_make_object_listr   r#   r$   )	r   r   r]   r"   rq   rr   lookup_kwargsr   rv   r   r   r   rw     s*    
  
z#BaseYearArchiveView.get_dated_itemsc                 C   s   | j S )zo
        Return `True` if this view should contain the full list of objects in
        the given year.
        )make_object_listr   r   r   r   r     s    z(BaseYearArchiveView.get_make_object_listN)r2   r3   r4   r5   r   r   rw   r   r   r   r   r   r     s
    r   c                   @   s   e Zd ZdZdZdS )YearArchiveViewr   Z_archive_yearNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdZdd ZdS )BaseMonthArchiveView+List of objects published in a given month.r)   c           
      C   s   |   }|  }|  }t||  ||  }| |}| | |}d| |d| |i}| jf |}| 	|}	|	||| 
|| |dfS )r   ro   rp   )r(   
next_monthprevious_month)r   r9   r_   r   r   r8   rn   r=   r   r   r:   r;   )
r   r   r(   r]   r"   rq   rr   r   r   rv   r   r   r   rw     s2       
  
z$BaseMonthArchiveView.get_dated_itemsN)r2   r3   r4   r5   r   rw   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdZdS )MonthArchiveViewr   Z_archive_monthNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdd ZdS )BaseWeekArchiveView*List of objects published in a given week.c              
   C   s   |   }|  }|  }|  }dddd}z|| }W n. tk
rf   td|dt|f Y nX |  }|dkr|dkrtd||f t	|||d	||}| 
|}	| 
| |}
d
| |	d| |
i}| jf |}d||| || |dfS )r   10)rY   rM   rZ   z'Unknown week format %r. Choices are: %sz, rZ   z%GzeISO week directive '%s' is incompatible with the year directive '%s'. Use the ISO year '%%G' instead.z%wro   rp   N)rP   Z	next_weekZprevious_week)r   rQ   r_   rO   r   r,   joinsortedr   r   rn   rW   r   rR   rS   )r   r   rP   r]   rN   Zweek_choicesZ
week_startr   r"   rq   rr   r   r   r   r   r   rw     sP    

  z#BaseWeekArchiveView.get_dated_itemsNr2   r3   r4   r5   rw   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdZdS )WeekArchiveViewr   Z_archive_weekNr   r   r   r   r   r   /  s   r   c                   @   s    e Zd ZdZdd Zdd ZdS )BaseDayArchiveView)List of objects published on a given day.c                 C   s@   |   }|  }|  }t||  ||  ||  }| |S r   )r   r9   rB   r   r   r8   rA   _get_dated_items)r   r   r(   r)   r"   r   r   r   rw   8  s    	z"BaseDayArchiveView.get_dated_itemsc              	   C   sD   |  |}| jf |}d||| || || || |dfS )z
        Do the actual heavy lifting of getting the dated items; this accepts a
        date object so that TodayArchiveView can be trivial.
        N)r)   Zprevious_dayZnext_dayr   r   )rs   r   rD   rC   r;   r:   )r   r"   r   r   r   r   r   r   I  s    
z#BaseDayArchiveView._get_dated_itemsN)r2   r3   r4   r5   rw   r   r   r   r   r   r   5  s   r   c                   @   s   e Zd ZdZdZdS )DayArchiveViewr   _archive_dayNr   r   r   r   r   r   ^  s   r   c                   @   s   e Zd ZdZdd ZdS )BaseTodayArchiveView List of objects published today.c                 C   s   |  tj S r   )r   rG   r"   todayr   r   r   r   rw   g  s    z$BaseTodayArchiveView.get_dated_itemsNr   r   r   r   r   r   d  s   r   c                   @   s   e Zd ZdZdZdS )TodayArchiveViewr   r   Nr   r   r   r   r   r   l  s   r   c                       s"   e Zd ZdZd fdd	Z  ZS )BaseDateDetailView
    Detail view of a single object on a single date; this differs from the
    standard DetailView by accepting a year/month/day in the URL.
    Nc                    s   |   }|  }|  }t||  ||  ||  }|dkrF|  n|}|  s|t	j
 krttd|jjj| jjd | |}|jf |}t j|dS )z%Get the object this request displays.NzZFuture %(verbose_name_plural)s not available because %(class_name)s.allow_future is False.)r   
class_name)r   )r   r9   rB   r   r   r8   rA   rc   ra   rG   r"   r   r   r   rb   rd   r   r^   r2   rs   r   super
get_object)r   r   r   r(   r)   r"   r   r   r^   r   r   r   x  s2    

zBaseDateDetailView.get_object)N)r2   r3   r4   r5   r   __classcell__r   r   r   r   r   r  s   r   c                   @   s   e Zd ZdZdZdS )DateDetailViewr   Z_detailNr   r   r   r   r   r     s   r    __c           	      C   sx   || | | | }t | | t | | t | }ztj|| W S  tk
rr   ttd||d Y nX dS )z
    Get a datetime.date object given a format string and a year, month, and day
    (only year is mandatory). Raise a 404 for an invalid date.
    uC   Invalid date string “%(datestr)s” given format “%(format)s”)datestrformatN)strrG   strptimer"   r,   r   r   )	r   r   r(   r7   r)   r@   delimr   r   r   r   r   r     s     r   c                 C   sL  |   }|  }|  }t| d| }t| d| }|||| }	}
|r|rd||	tjdd }n|
}|sv|t krz|S dS n|rd| | |	i}d| }nd| | |
i}|}|s| jrt	
 }nt }||d	| < |  jf ||}zt|d
 |}W n tk
r   Y dS X | jr@tjr8t	|}| }||S dS )aV  
    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.

    However in essence the logic comes down to:

        * If allow_empty and allow_future are both true, this is easy: just
          return the naive result (just the next/previous day/week/month,
          regardless of object existence.)

        * If allow_empty is true, allow_future is false, and the naive result
          isn't in the future, then return it; otherwise return None.

        * If allow_empty is false and allow_future is true, return the next
          date *that contains a valid object*, even if it's in the future. If
          there are no next objects, return None.

        * If allow_empty is false and allow_future is false, return the next
          date that contains a valid object. If that date is in the future, or
          if there are no next objects, return None.
    z_get_current_%sz_get_next_%sr&   rE   Nrp   r|   ro   r   r   )r_   r   ra   getattrrG   rH   r   rn   rh   r   r   rc   r   Zorder_by
IndexErrorr   rl   	localtimer"   )Zgeneric_viewr"   r   r   r]   r   r`   Zget_currentZget_nextstartendresultr   r}   r   r   r   r   r   r      sB    


r    c                   C   s   t jrt S tj S dS )z1Return the current date in the current time zone.N)r   rl   r   Z	localdaterG   r"   r   r   r   r   r   r     s    r   )r   r   r   r   r   )/rG   Zdjango.confr   Zdjango.core.exceptionsr   Z	django.dbr   Zdjango.httpr   Zdjango.utilsr   Zdjango.utils.functionalr   Zdjango.utils.translationr   r   Zdjango.views.generic.baser	   Zdjango.views.generic.detailr
   r   Zdjango.views.generic.listr   r   r   r6   r?   rL   r\   rt   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r   r   r   <module>   sL   25/@CW.$4),
         
Z