объединить django-filter DateTimeFromToRangeFilter и DateTimeInput (datepicker)

Использование django_filter и datetimeinput как средство выбора даты, я пытаюсь добавить ввод даты и времени, поля FROM и TO.

Мне удалось использовать dateinput только с одним полем из форм django или из фильтра django DateTimeFromToRangeFilter без отображения выбора даты (только ввод текста вручную).

Вот мой filter_model.py для одного поля с выбором даты.

from app.models.api_status import ApiStatus
import django_filters
from django import forms

class DateTimeInput(forms.DateTimeInput):
    input_type = 'date'

    # working solution for just 1 date field
class ApiStatusFilter(django_filters.FilterSet):
    date_time = django_filters.DateFilter(
        label=('With start date'),
        lookup_expr=('icontains'), # use contains,
        widget=DateTimeInput()
    )
    class Meta:
        model = ApiStatus
        fields = ['id', 'date_time']

На рисунке показано всплывающее окно выбора даты, на которое можно нажать.

введите описание изображения здесь

Вот мой filter_model.py для двух полей, ОТ и ДО, без выбора даты.

from app.models.api_status import ApiStatus
import django_filters
from django import forms

class DateTimeInput(forms.DateTimeInput):
    input_type = 'date'


class ApiStatusFilter(django_filters.FilterSet):
    date_time =django_filters.DateTimeFromToRangeFilter()

    class Meta:
        model = ApiStatus
        fields = ['id', 'date_time']
        widgets = {
            'date_time': forms.DateTimeInput(attrs={'placeholder':'Select a date'})
        }

На рисунке ниже показан ввод текста вручную без всплывающего окна выбора даты. введите описание изображения здесь

Вот мой файл шаблона, хотя я не сильно его менял, когда пробовал два подхода, описанных выше. status_template.html

{% load static %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <link rel="stylesheet" type="text/css" href="{% static 'css/table_styling.css' %}">
        <meta charset="UTF-8">
        <title>Test Site</title>
        {% comment %}
        <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <link rel="stylesheet" href="/resources/demos/style.css"> 
        <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
        {% endcomment %}
    </head>

    <body>
        <table>
            <thead>
                <tr>
                    {% for keys in dictionarys.keys %} 
                        <th>{{ keys }}</th>
                    {% endfor %}
                </tr>
            </thead>
            <tbody>
                <form method="get">
                    {{ apistatus_filter.form.as_p }}
                    <button type="submit">Search</button>
                        {% for user in dataqs.object_list %}
                        <tr>
                            <td>{{ user.id }}</td>
                            <td>{{ user.date_time }}</td>
                        {% endfor %}
                </form>
            </tbody>
        </table>
        {% comment %} <script>
            $( function() {
            $("#datepicker").datepicker();
            } );
        </script> {% endcomment %}
    </body>
</html>

Я изучил множество источников здесь и в других местах. Я пробовал использовать MultiWidget и jQuery, но они еще не работали. Мысли? Заранее спасибо.


person Elia Ahadi    schedule 22.02.2019    source источник


Ответы (2)


Можно использовать javascript, чтобы поля диапазона имели класс datepicker.

Я изо всех сил пытался заставить jQuery datepicker работать с DateTimeFromToRangeFilter из Django Filters в сочетании с RangeWidget. Почему-то кажется, что RangeWidget не принимает class: datepicker.

Filters.py:

dtoriginal = django_filters.DateTimeFromToRangeFilter(lookup_expr='icontains',
    widget=django_filters.widgets.RangeWidget(
        attrs={
            'placeholder': 'yyyy-mm-dd',
        },
    ),
    label = 'Date Original'
)

Я изменил свой шаблон поиска html, включив в него следующий сценарий:

<form method="get">
  {{ filter.form.as_p }}

  <script>
    $(function () {
      $("id_dtoriginal_0").datepicker();
      $("id_dtoriginal_1").datepicker();
    });
  </script>

  {% if filter.is_bound %}
    <button onclick=...></button
  {% endif %}
</form>

Где dtoriginal - имя поля в модели. _0 и _1 - это поля «от» и «до», созданные RangeWidget.

Надеюсь, это поможет, я часами пытался понять, как это сделать с помощью django-фильтров, но безуспешно.

person Bird    schedule 18.11.2019

Мне удалось решить эту проблему без внешних зависимостей (без jquery), просто использовал локальный ввод по дате и времени и DateTimeFromToRangeFilter с виджетом Range. Возможно, не самое идеальное решение, но это один из способов сделать это.

Коды моей модели, фильтра, представления и шаблона приведены ниже.

model.py

from app.modules.string_handler import StringHandler
from django.db.models.signals import post_save
import datetime

class ApiStatus(models.Model):
    id = models.AutoField(primary_key=True)
    date_time = models.DateTimeField("Date_Time", default=datetime.datetime.now(), blank=True)

    class Meta:
        managed = True
        db_table = 'api_status'
        verbose_name = 'API STATUS'

    def __str__(self):
        "A string representation of the model."
        return f'{self.id},{self.token},{self.date_time},{self.status},{self.summary},{self.log}'

    def __unicode__(self):
        return self.created_at

filter.py

from app.models.api_status import ApiStatus
import django_filters
from django import forms

class ApiStatusFilter(django_filters.FilterSet):

    date_time = django_filters.DateTimeFromToRangeFilter(
        lookup_expr=('icontains'),
        widget=django_filters.widgets.RangeWidget(
            attrs={'type':'datetime-local'}
        )
    )

    class Meta:
        model = ApiStatus
        fields = ['id', 'date_time']

view.py

from django.shortcuts import render
from app.models.filters_model import ApiStatusFilter
from app.models.api_status import ApiStatus
import requests
from django import forms

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
import urllib
from datetime import datetime, timedelta

def status(request):
    apistatus_list = ApiStatus.objects.all()

    request.GET2 = request.GET.copy()

    if request.GET2.get('date_time_min'):
        request.GET2['date_time_min'] = datetime.strptime(request.GET2['date_time_min'],"%Y-%m-%dT%H:%M").strftime("%Y-%m-%d %H:%M")
    if request.GET2.get('date_time_max'):
        request.GET2['date_time_max'] = datetime.strptime(request.GET2['date_time_max'],"%Y-%m-%dT%H:%M").strftime("%Y-%m-%d %H:%M")

    apistatus_filter = ApiStatusFilter(request.GET2, queryset=apistatus_list)

    paginator = Paginator(apistatus_filter.qs, 10)
    page = request.GET.get('page')

    try:
        dataqs = paginator.page(page)
    except PageNotAnInteger:
        dataqs = paginator.page(1)
    except EmptyPage:
        dataqs = paginator.page(paginator.num_pages)

    return render(request, 'status_page_template.html', {'table_col_DATA':all_entries_ordered, 'dictionarys': dictionarys, 'apistatus_filter': apistatus_filter, 'dataqs': dataqs, 'allobjects': apistatus_list})

template.html

{% load my_templatetags %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <link rel="stylesheet" type="text/css" href="{% static 'css/search_form_table_styling.css' %}">
        <meta charset="UTF-8">
        <title>TEST Site</title>
    </head>

    <body>
        <form method="get" action="">
            <div class="search_form_wrapper">
                <div class="id_box">ID:{{ apistatus_filter.form.id }}</div>
                <div class="id_box">Date_Time:{{ apistatus_filter.form.date_time }}</div>
            </div>

            <input type="submit" value="Submit" class="search_form_submit">
        </form>

        <table>
            <tbody>
                {% for user in dataqs.object_list %}
                    <tr>
                        <td>{{ user.id }}</td>
                        <td>{{ user.date_time }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>

        <div class="pagination">
            <span>
                {% if dataqs.has_previous %}
                    <a href="?{% query_transform request page=1 %}">&laquo; first</a>
                    <a href="?{% query_transform request page=dataqs.previous_page_number %}">previous</a>
                {% endif %}

                <span class="current">
                    Page {{ dataqs.number }} of {{ dataqs.paginator.num_pages }}.
                </span>

                {% if dataqs.has_next %}
                    <a href="?{% query_transform request page=dataqs.next_page_number %}">next</a>
                    <a href="?{% query_transform request page=dataqs.paginator.num_pages %}">last &raquo;</a>
                {% endif %}
            </span>
        </div> 
    </body>
</html>
person Elia Ahadi    schedule 04.03.2019