morlandi / django-ajax-datatable

A Django app which provides the integration of a Django project with the jQuery Javascript library DataTables.net
MIT License
204 stars 64 forks source link

date filters on DateTime #125

Open alit990 opened 5 months ago

alit990 commented 5 months ago

Thank you very much for your efforts Is there a possibility to filter date_time in the library? I want to filter the date column from a certain time to a certain time.

elementace commented 4 months ago

I believe this library has this built in. You can enable filtering (standard datatables offering) by configuring the dom on instantiation by adding 'f' to the dom argument:

AjaxDatatableViewUtils.initialize_table( $('.my_table_div_object_id'), 'insert_my_ajax_url_here' { ... dom: 'Brtfip', ... },

Personally I didn't like the location of where this was on the page, so I added my own form using crispy forms, and tempus dominus date picker

from tempus_dominus.widgets import DatePicker

class SearchForm(forms.Form):
    search_string = forms.CharField(label="Search", max_length=100)
    date_from = forms.DateTimeField(label="Date From", required=False)
    date_to = forms.DateTimeField(label="Date To", required=False)

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super(SearchForm, self).__init__(*args, **kwargs)
        for field_name in ("date_from", "date_to"):
            self.fields[field_name] = forms.DateTimeField(
                widget=DatePicker(
                    options={
                        "useCurrent": True,
                        "collapse": True,
                    },
                    attrs={
                        "append": "fa fa-calendar",
                        "icon_toggle": True,
                    },
                ),
            )
            self.fields[
                field_name
            ].label = f"<small>{self.fields[field_name].label}</small>"
            self.fields[field_name].input_formats = ["%d/%m/%Y"]
            self.fields[field_name].required = False
        self.fields["search_string"].label = ""
        self.fields["search_string"].required = False
from .forms import SearchForm

def my_page_view(request: HttpRequest) -> HttpResponse:
    context = {
        "my_form": SearchForm(),
    }
    return render(request, "app_module/page_template.html", context)

and over-rode the filter_queryset function of the AjaxDatatableView:

def dt_strptime(input_str: str) -> datetime:
    try:
        dt = datetime.strptime(input_str, "%d/%m/%Y")
    except:
        dt = datetime.strptime(input_str, "%m/%d/%Y")
    return dt

class MyAjaxView(AjaxDatatableView):
    def filter_queryset(self, params: Any, qs: Any) -> Any:
        sSearch = params.get("search_value")
        if params.get("date_from"):
            qs = qs.filter(
                created_at__gte=dt_strptime(params.get("date_from"))
            )
        if params.get("date_to"):
            qs = qs.filter(
                created_at__lte=dt_strptime(params.get("date_to"))
            )
        if sSearch:
            qs = (
                qs.filter(
                        Q(order__shop_order_number__icontains=sSearch)
                )
           )
        return qs

using crispy forms add the form to the page (including the tempus_dominus date picker)

{% load crispy_forms_tags %}
    {{ my_form.media }}
                       <div class="row">
                              <div class="col-6 col-md-12 col-lg-12">
                                  <div class="form-group">
                                      <h6 class="heading-small text-muted">{% trans "Search" %}</h6>
                                      <div class="mt--2">
                                        {{ my_form.search_string|as_crispy_field }}
                                      </div>
                                  </div>
                              </div>
                        </div>
                       <div class="row">
                              <div class="col-6 col-md-12 col-lg-12">
                                  <div class="form-group">
                                      <h6 class="heading-small text-muted">{% trans "Date From" %}</h6>
                                      <div class="mt--2">
                                        {{ my_form.date_from }}
                                      </div>
                                  </div>
                              </div>
                              <div class="col-6 col-md-12 col-lg-12">
                                  <div class="form-group">
                                      <h6 class="heading-small text-muted">{% trans "Date To" %}</h6>
                                      <div class="mt--2">
                                        {{ my_form.date_to }}
                                      </div>
                                  </div>
                              </div>
                        </div>

Make sure my javascript updates whenever a filter is added

<script>
        const redraw = function(reload=true){
            if(reload){
                $('.sales').DataTable().ajax.reload(null, false);
            }
        }
        $(document).ready(function() {
            AjaxDatatableViewUtils.initialize_table(
                $('.my_table_id'),
                '{% url "ajax_datatable_url_name" %}',
                {
                    autoWidth: true,
                    responsive: true,
                    processing: true,
                    serverSide: true,
                    stateSave: true,
                    dom: 'Brtip',
                    pageLength: 15,
                },
                {
                    length: 15,
                    date_from: function() { return $('input#id_date_from').val() },
                    date_to: function() { return $('input#id_date_to').val() },
                    custom_search: function() {
                        return $('input#id_search_string').val();
                    },
                }
            );
            $("#id_date_from").on("change.datetimepicker", function (event) {
                redraw();
            });
            $("#id_date_to").on("change.datetimepicker", function (event) {
                 redraw();
            });
            $('#div_id_search_string input').on('change paste keyup', function() {
                 redraw();
            });
           });
</script>