silentsokolov / django-admin-rangefilter

A Django app that lets you filter data by date range and numeric range in the admin UI
MIT License
713 stars 106 forks source link

Support django-grappelli #84

Open abhakhi opened 2 years ago

abhakhi commented 2 years ago

With django-grappelli, the date fields show up as edit boxes. While they work, would be better if date picker fields are used.

Might be duplicate of #55.

silentsokolov commented 2 years ago

Grappelli doesn't support #35 #14 #12

You are welcome to help with PR.

jrobichaud commented 7 months ago

I managed to have django-admin-rangefilter working with grappelli in my project. I hope it can help anyone wanting to finish the job.

image

I created an app rangefilter_grappelli to store all the hacks.

It still has css issues but at least it works.

app structure

rangefilter_grappelli/
rangefilter_grappelli/templates/admin/change_list.html
rangefilter_grappelli/templates/admin/change_list_filter_sidebar.html
rangefilter_grappelli/templatetags/__init__.py
rangefilter_grappelli/templatetags/grp_tags_overrides.py
rangefilter_grappelli/__init__.py
rangefilter_grappelli/apps.py

code

settings.py

Add rangefilter_grappelli in your project's django settings, make sure to add it before grappelli.

INSTALLED_APPS = [
    # ...
    "rangefilter_grappelli",  # <- make sure it is before grappelli or the template overrides will not work
    "rangefilter",
    "grappelli",
    "django.contrib.admin",
    # ...
]

rangefilter_grappelli/templatetags/grp_tags_overrides.py:

This script overrides admin_list_filter template tag contained in grappelli/templatetags/grp_tags.py.

This implementation detects first if it is a template from rangefilter and will use rangefilter's code instead of grappelli's when applicable.

from django.apps import apps

try:
    apps.get_app_config("grappelli")
except LookupError:
    pass
else:
    from django.contrib.admin.templatetags.admin_list import (
        admin_list_filter as __django_admin_list_filter,
    )
    from grappelli.templatetags.grp_tags import (
        admin_list_filter as __grappelli_admin_list_filter,
        register,
    )

    @register.simple_tag
    def admin_list_filter(cl, spec):
        template_path = spec.template
        if "rangefilter" in template_path:
            return __django_admin_list_filter(cl, spec)
        return __grappelli_admin_list_filter(cl, spec)

rangefilter_grappelli/apps.py

Just a basic app config, no magic here.

from django.apps import AppConfig

class RangefilterGrappelliConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "rangefilter_grappelli"

templates

The templates override their respective grappelli templates to force the date time pickers to be initialized. Otherwise the picker buttons will not appear unless list_editable is used.

rangefilter_grappelli/templates/admin/change_list.html

{% extends "admin/change_list.html" %}

{% block javascripts %}
{{ block.super }}
<script type="text/javascript" charset="utf-8">
    (function($) {
        $(document).ready(function() {
            grappelli.initDateAndTimePicker();
        });
    })(grp.jQuery);
</script>
{% endblock %}

rangefilter_grappelli/templates/admin/change_list_filter_sidebar.html

{% extends "admin/change_list_filter_sidebar.html" %}

{% block javascripts %}
{{ block.super }}
<script type="text/javascript" charset="utf-8">
    (function($) {
        $(document).ready(function() {
            grappelli.initDateAndTimePicker();
        });
    })(grp.jQuery);
</script>
{% endblock %}