Metadata-Version: 1.1
Name: django-admin-lightweight-date-hierarchy
Version: 0.3.0
Summary: Using django admin date hierarchy queries free!
Home-page: https://github.com/hakib/django-admin-lightweight-date-hierarchy
Author: Haki Benita
Author-email: hakibenita@gmail.com
License: MIT, Django
Description: =============================
        Django Admin lightweight date hierarchy
        =============================
        
        .. image:: https://badge.fury.io/py/django-admin-lightweight-date-hierarchy.svg
            :target: https://badge.fury.io/py/django-admin-lightweight-date-hierarchy
        
        .. image:: https://travis-ci.org/hakib/django-admin-lightweight-date-hierarchy.svg?branch=master
            :target: https://travis-ci.org/hakib/django-admin-lightweight-date-hierarchy
        
        .. image:: https://codecov.io/gh/hakib/django-admin-lightweight-date-hierarchy/branch/master/graph/badge.svg
            :target: https://codecov.io/gh/hakib/django-admin-lightweight-date-hierarchy
        
        
        Django Admin date_hierarchy with zero queries
        ----------------------------------------------
        
        The built-in `date_hierarchy`_ tag performs a query to find the dates for which there is data.
        On large tables this query can be very expensive.
        
        To prevent additional queries, set ``date_hierarchy_drilldown = False`` on the ``ModelAdmin``.
        When drill-down is disabled the tag will generate a default range of dates based solely
        on the selected hierarchy level - without performing a query.
        
        Default options for hierarchy levels:
        
        - None - +-3 years from current year.
        - Year - all months of the selected year.
        - Month - all days of the selected month.
        
        When ``date_hierarchy_drilldown = True`` or when not set the default behaviour is preserved.
        
        .. _`date_hierarchy`: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.date_hierarchy
        
        
        Support
        ----------
        
        Python 2.7, 3.4, 3.5, 3.6
        
        Django 1.9, 1.10, 1.11
        
        
        Quickstart
        ----------
        
        Install django-admin-lightweight-date-hierarchy::
        
            pip install django-admin-lightweight-date-hierarchy
        
        Add it to your `INSTALLED_APPS`:
        
        .. code-block:: python
        
            INSTALLED_APPS = (
                ...
                'django_admin_lightweight_date_hierarchy',
                ...
            )
        
        Add the following to any ``ModelAdmin`` with ``date_hierarchy`` to prevent the default drill-down behaviour:
        
        .. code-block:: python
        
            @admin.register(MyModel)
            class MyModelAdmin(admin.ModelAdmin):
                date_hierarchy = 'created'
                date_hierarchy_drilldown = False
        
        
        To change the default dates generated by the template tag for any level in the hierarchy, implement a
        function called ``get_date_hierarchy_drilldown(self, year_lookup=None, month_lookup=None)`` on the ``ModelAdmin``.
        The function receives the date hierarchy filter and is expected to return a list of dates to offer for drill-down.
        
        For example, a custom drill-down that offers only past dates:
        
        
        .. code-block:: python
        
        
            import datetime
            import calendar
        
            from django.utils import timezone
            from django.contrib import admin
        
        
            @admin.register(MyModel)
            class MyModelAdmin(admin.ModelAdmin):
                date_hierarchy = 'created'
                date_hierarchy_drilldown = False
        
                def get_date_hierarchy_drilldown(self, year_lookup, month_lookup):
                    """Drill-down only on past dates."""
        
                    today = timezone.now().date()
        
                    if year_lookup is None and month_lookup is None:
                        # Past 3 years.
                        return (
                            datetime.date(y, 1, 1)
                            for y in range(today.year - 2, today.year + 1)
                        )
        
                    elif year_lookup is not None and month_lookup is None:
                        # Past months of selected year.
                        this_month = today.replace(day=1)
                        return (
                            month for month in (
                                datetime.date(int(year_lookup), month, 1)
                                for month in range(1, 13)
                            ) if month <= this_month
                        )
        
                    elif year_lookup is not None and month_lookup is not None:
                        # Past days of selected month.
                        days_in_month = calendar.monthrange(year_lookup, month_lookup)[1]
                        return (
                            day for day in (
                                datetime.date(year_lookup, month_lookup, i + 1)
                                for i in range(days_in_month)
                            ) if day <= today
                        )
        
        
        RangeBasedDateHierarchyListFilter
        ----------------------------------------------
        
        Django filters the queryset for a given level in the date hierarchy using a database
        function to extract the relevent date part. For example, when filtering a queryset on
        a `created` date field for November 2017, Django will execute the following query:
        
        .. code-block:: sql
        
            SELECT
                ...
            FROM
                app_model
            WHERE
                created BETWEEN '2017-01-01 00:00:00' AND '2017-12-31 23:59:59.999999'
                AND EXTRACT('month', created) = 11
        
        A function is opaque to the database optimizer. If you have a range-based (btree) index
        on the field, using EXTRACT does not limit the range at all, and so the index is not
        utilized properly which might lead to a sub optimal execution plan.
        
        There are several approaches to tackle this issue. For exmaple, in databases that support
        function based indexes the developer can add an index on the specific function to try and
        improve the performace of the query. The downside to this approach is having to maintain
        additional indexes for each level of the hierarchy. Additional indexes slow down insert
        and update operations, and take up space.
        
        Another approach is to simplify the condition used by Django to filter the queryset
        for any given level in the hierarchy:
        
        .. code-block:: sql
        
            SELECT
                ...
            FROM
                app_model
            WHERE
                created >= '2017-11-01 00:00:00'
                AND created < '2017-12-01 00:00:00'
        
        
        This is what RangeBasedDateHierarchyListFilter does.
        
        To achieve the above query, simply add the following to your ModelAdmin:
        
        .. code-block:: python
        
        
            from django.contrib import admin
            from django_admin_lightweight_date_hierarchy.admin import RangeBasedDateHierarchyListFilter
        
        
            @admin.register(MyModel)
            class MyModelAdmin(admin.ModelAdmin):
                date_hierarchy = 'created'
        
                list_filters = (
                    RangeBasedDateHierarchyListFilter,
                )
        
        
        Blog Post
        ----------
        
        You can read more about this package in my blog post `scaling django admin date hierarchy`_.
        
        .. _`scaling django admin date hierarchy`: https://medium.com/@hakibenita/scaling-django-admin-date-hierarchy-85c8e441dd4c
        
        
        Running Tests
        -------------
        
        ::
        
            source <YOURVIRTUALENV>/bin/activate
            (venv) $ pip install tox
            (venv) $ tox
        
        
        Credits
        -------
        
        Tools used in rendering this package:
        
        *  Cookiecutter_
        *  `cookiecutter-djangopackage`_
        
        .. _Cookiecutter: https://github.com/audreyr/cookiecutter
        .. _`cookiecutter-djangopackage`: https://github.com/pydanny/cookiecutter-djangopackage
        
        
        
        
        History
        -------
        
        0.3.0 (2017-11-24)
        ++++++++++++++++++
        
        * Added RangeBasedDateHierarchyListFilter.
        
        0.2.0 (2017-10-21)
        ++++++++++++++++++
        
        * Option to provide custom drill down for any level in the hierarchy.
        
        
        0.1.0 (2017-09-21)
        ++++++++++++++++++
        
        * First release on PyPI.
        
Keywords: django-admin-lightweight-date-hierarchy
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django
Classifier: Framework :: Django :: 1.9
Classifier: Framework :: Django :: 1.10
Classifier: Framework :: Django :: 1.11
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
