0001-add-date-and-time-filters-for-resource-logs-14671.patch
passerelle/base/forms.py | ||
---|---|---|
1 |
from datetime import datetime, time |
|
2 | ||
1 | 3 |
from django import forms |
2 | 4 | |
3 | 5 |
from .models import ApiUser, AccessRight |
... | ... | |
17 | 19 |
'resource_type': forms.HiddenInput(), |
18 | 20 |
'resource_pk': forms.HiddenInput(), |
19 | 21 |
} |
22 | ||
23 | ||
24 |
class CustomDateInput(forms.DateInput): |
|
25 |
input_type = 'date' |
|
26 | ||
27 | ||
28 |
class CustomTimeInput(forms.TimeInput): |
|
29 |
input_type = 'time' |
|
30 | ||
31 | ||
32 |
class LogFilterForm(forms.Form): |
|
33 |
date__gte = forms.DateField(required=False, widget=CustomDateInput) |
|
34 |
time__gte = forms.TimeField(required=False, widget=CustomTimeInput, initial=time(0, 0)) |
|
35 |
date__lte = forms.DateField(required=False, widget=CustomDateInput) |
|
36 |
time__lte = forms.TimeField(required=False, widget=CustomTimeInput, initial=time(0, 0)) |
|
37 |
order_by = forms.ChoiceField(required=False, |
|
38 |
choices=(('timestamp', 'timestamp'), ('-timestamp', '-timestamp')), |
|
39 |
initial=('-timestamp', '-timestamp')) |
|
40 |
page = forms.IntegerField(required=False, initial=1, min_value=1) |
|
41 |
page_size = forms.IntegerField(required=False, initial=10, min_value=1, max_value=1000) |
|
42 | ||
43 |
def prepare_query(self): |
|
44 |
'''Transform input to datetime lte and gte dictionnary |
|
45 |
''' |
|
46 |
query_filter = {} |
|
47 |
if self.cleaned_data.get('date__gte'): |
|
48 |
time__gte = self.cleaned_data['time__gte'] or time(0,0) |
|
49 |
query_filter.update({ |
|
50 |
'timestamp__gte': datetime.combine(self.cleaned_data.get('date__gte'), time__gte)}) |
|
51 |
if self.cleaned_data.get('date__lte'): |
|
52 |
time__lte = self.cleaned_data['time__lte'] or time(0,0) |
|
53 |
query_filter.update({ |
|
54 |
'timestamp__lte': datetime.combine(self.cleaned_data.get('date__lte'), time__lte)}) |
|
55 |
return query_filter, { |
|
56 |
'page': self.cleaned_data['page'], |
|
57 |
'page_size': self.cleaned_data['page_size'], |
|
58 |
'order_by': self.cleaned_data['order_by'] |
|
59 |
} |
passerelle/base/templatetags/passerelle.py | ||
---|---|---|
1 | 1 |
from __future__ import absolute_import |
2 |
import urllib |
|
2 | 3 | |
3 | 4 |
from django import template |
5 |
from django.core.urlresolvers import reverse |
|
4 | 6 |
from django.contrib.contenttypes.models import ContentType |
5 | 7 |
from django.contrib.auth import get_permission_codename |
6 | 8 |
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
9 |
from django.utils.dateparse import parse_datetime |
|
10 |
from django.db.models import Q |
|
7 | 11 | |
8 | 12 |
from passerelle.utils import get_trusted_services |
9 | 13 |
from ..models import AccessRight, ResourceLog |
14 |
from ..forms import LogFilterForm |
|
10 | 15 | |
11 | 16 |
register = template.Library() |
12 | 17 | |
... | ... | |
22 | 27 |
context['trusted_services'] = get_trusted_services() |
23 | 28 |
return context |
24 | 29 | |
30 |
def get_resource_log_query(request): |
|
31 |
query_params = { |
|
32 |
'page': 1, |
|
33 |
'page_size': 10, |
|
34 |
'order_by': '-timestamp' |
|
35 |
} |
|
36 |
query_filter = {} |
|
37 |
get = request.GET.dict() |
|
38 |
# Add search parameters from request.GET |
|
39 |
for param in ['page', 'order_by', 'page_size']: |
|
40 |
try: |
|
41 |
query_params[param] = get.pop(param) |
|
42 |
except KeyError: |
|
43 |
continue |
|
44 |
# Add query filters from request.GET |
|
45 |
for key, value in get.items(): |
|
46 |
if key.startswith('timestamp'): |
|
47 |
datetime_obj = parse_datetime(value) |
|
48 |
if datetime_obj: |
|
49 |
query_filter[key] = datetime_obj |
|
50 | ||
51 |
return query_filter, query_params |
|
52 | ||
53 | ||
54 |
def post_resource_log_query(logfilterform): |
|
55 |
'''Add search parameters from From''' |
|
56 |
query_params = {} |
|
57 |
query_filter = {} |
|
58 |
if logfilterform.is_valid(): |
|
59 |
query_filter, query_params = logfilterform.prepare_query() |
|
60 |
return query_filter, query_params |
|
61 | ||
25 | 62 | |
26 | 63 |
@register.inclusion_tag('passerelle/includes/resource-logs-table.html', takes_context=True) |
27 | 64 |
def resource_logs_table(context, resource): |
65 |
'''Logs table with customizable pagination and timestamp filters |
|
66 |
''' |
|
28 | 67 |
request = context.get('request') |
29 |
page = request.GET.get('page', 1) |
|
30 | ||
31 | 68 |
connector = resource.get_connector_slug() |
32 |
context['connector'] = connector |
|
33 |
context['slug'] = resource.slug |
|
34 |
qs = ResourceLog.objects.filter(appname=connector, slug=resource.slug).order_by('-timestamp') |
|
69 |
# defaults params |
|
70 |
query_params = { |
|
71 |
'page': 1, |
|
72 |
'page_size': 10, |
|
73 |
'order_by': '-timestamp' |
|
74 |
} |
|
75 |
query_filter = {} |
|
76 |
# Add search parameters from request query |
|
77 |
if request.method == 'GET': |
|
78 |
query_filter, query_params = get_resource_log_query(request) |
|
79 |
# GET params initialize the Form data |
|
80 |
date__gte, time__gte, date__lte, time__lte = False, False, False, False |
|
81 |
if query_filter.get('timestamp__gte'): |
|
82 |
date__gte = query_filter['timestamp__gte'].date().isoformat() |
|
83 |
time__gte = query_filter['timestamp__gte'].time() |
|
84 |
if query_filter.get('timestamp__lte'): |
|
85 |
date__lte = query_filter['timestamp__lte'].date() |
|
86 |
time__lte = query_filter['timestamp__lte'].time().isoformat() |
|
87 | ||
88 |
logfilterform = LogFilterForm(data=dict({ |
|
89 |
'date__gte': date__gte or None, |
|
90 |
'time__gte': time__gte or None, |
|
91 |
'date__lte': date__lte or None, |
|
92 |
'time__lte': time__lte or None |
|
93 |
}, **query_params)) |
|
94 |
else: |
|
95 |
logfilterform = LogFilterForm(data=request.POST) |
|
96 |
query_filter, query_params = post_resource_log_query(logfilterform) |
|
97 | ||
98 |
if len(query_filter.keys()): |
|
99 |
qs = ResourceLog.objects.filter(Q(**query_filter)) |
|
100 |
qs = qs.filter(appname=connector, slug=resource.slug) |
|
101 |
else: |
|
102 |
qs = ResourceLog.objects.filter(appname=connector, slug=resource.slug) |
|
35 | 103 | |
36 |
paginator = Paginator(qs, 10) |
|
104 |
qs = qs.order_by(query_params['order_by']) |
|
105 |
paginator = Paginator(qs, int(query_params['page_size'])) |
|
37 | 106 |
try: |
38 |
logrecords = paginator.page(page)
|
|
107 |
logrecords = paginator.page(query_params['page'])
|
|
39 | 108 |
except PageNotAnInteger: |
40 | 109 |
logrecords = paginator.page(1) |
41 | 110 |
except (EmptyPage,): |
42 | 111 |
logrecords = paginator.page(paginator.num_pages) |
43 | 112 | |
44 |
context['logrecords'] = logrecords |
|
113 |
context.update({ |
|
114 |
'logfilterform': logfilterform, |
|
115 |
'query_filter': query_filter, |
|
116 |
'query_params': query_params, |
|
117 |
'logrecords': logrecords, |
|
118 |
'permalink': reverse('view-connector', args=(connector, resource.slug)) + '?' + urllib.urlencode(dict(query_filter, **query_params)) |
|
119 |
}) |
|
45 | 120 |
return context |
46 | 121 | |
47 | 122 |
passerelle/templates/passerelle/includes/resource-logs-table.html | ||
---|---|---|
2 | 2 |
{% load tz %} |
3 | 3 | |
4 | 4 |
{% block content %} |
5 |
<form action="." method="POST" id="logfilter" style="padding:1em; border: 1px solid gray;"> |
|
6 |
{% csrf_token %} |
|
7 |
{{ logfilterform }} |
|
8 |
<input type="submit" id="_submit" style="height: 3.3rem;"> |
|
9 |
</form> |
|
5 | 10 |
{% if logrecords %} |
6 | 11 |
<table class="main"> |
7 | 12 |
<thead> |
... | ... | |
19 | 24 |
{% endfor %} |
20 | 25 |
</tbody> |
21 | 26 |
</table> |
22 | ||
23 |
{% with page_obj=logrecords %} |
|
24 |
{% include "gadjo/pagination.html" with anchor="#logs" %} |
|
25 |
{% endwith %} |
|
26 | ||
27 | 27 |
{% else %} |
28 | 28 |
<p>{% trans 'No records found' %}</p> |
29 | 29 |
{% endif %} |
30 |
<a href="{{ permalink }}">{% trans "Link to the results" %}</a> |
|
30 | 31 |
{% endblock %} |
passerelle/views.py | ||
---|---|---|
137 | 137 |
template_names.append('passerelle/manage/service_view.html') |
138 | 138 |
return template_names |
139 | 139 | |
140 |
def post(self, request, *args, **kwargs): |
|
141 |
return self.get(request, *args, **kwargs) |
|
142 | ||
140 | 143 | |
141 | 144 |
class GenericCreateConnectorView(GenericConnectorMixin, CreateView): |
142 | 145 |
template_name = 'passerelle/manage/service_form.html' |
143 |
- |