mirror of
https://github.com/django-helpdesk/django-helpdesk.git
synced 2025-08-09 08:05:13 +02:00
Refactor query code into customizable class
This commit is contained in:
@ -1,12 +1,16 @@
|
||||
from django.db.models import Q
|
||||
from django.core.cache import cache
|
||||
|
||||
from model_utils import Choices
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from base64 import b64encode
|
||||
from base64 import b64decode
|
||||
import json
|
||||
|
||||
from model_utils import Choices
|
||||
|
||||
from helpdesk.serializers import DatatablesTicketSerializer
|
||||
|
||||
|
||||
def query_to_base64(query):
|
||||
"""
|
||||
@ -47,60 +51,26 @@ def query_to_dict(results, descriptions):
|
||||
return output
|
||||
|
||||
|
||||
def apply_query(queryset, params):
|
||||
"""
|
||||
Apply a dict-based set of filters & parameters to a queryset.
|
||||
|
||||
queryset is a Django queryset, eg MyModel.objects.all() or
|
||||
MyModel.objects.filter(user=request.user)
|
||||
|
||||
params is a dictionary that contains the following:
|
||||
filtering: A dict of Django ORM filters, eg:
|
||||
{'user__id__in': [1, 3, 103], 'title__contains': 'foo'}
|
||||
|
||||
search_string: A freetext search string
|
||||
|
||||
sorting: The name of the column to sort by
|
||||
"""
|
||||
for key in params['filtering'].keys():
|
||||
filter = {key: params['filtering'][key]}
|
||||
queryset = queryset.filter(**filter)
|
||||
|
||||
search = params.get('search_string', '')
|
||||
if search:
|
||||
qset = (
|
||||
Q(title__icontains=search) |
|
||||
Q(description__icontains=search) |
|
||||
Q(resolution__icontains=search) |
|
||||
Q(submitter_email__icontains=search) |
|
||||
Q(ticketcustomfieldvalue__value__icontains=search)
|
||||
)
|
||||
|
||||
queryset = queryset.filter(qset)
|
||||
|
||||
sorting = params.get('sorting', None)
|
||||
if sorting:
|
||||
sortreverse = params.get('sortreverse', None)
|
||||
if sortreverse:
|
||||
sorting = "-%s" % sorting
|
||||
queryset = queryset.order_by(sorting)
|
||||
|
||||
return queryset
|
||||
def get_search_filter_args(search):
|
||||
if search.startswith('queue:'):
|
||||
return Q(queue__title__icontains=search[len('queue:'):])
|
||||
if search.startswith('priority:'):
|
||||
return Q(priority__icontains=search[len('priority:'):])
|
||||
return (
|
||||
Q(id__icontains=search) |
|
||||
Q(title__icontains=search) |
|
||||
Q(description__icontains=search) |
|
||||
Q(priority__icontains=search) |
|
||||
Q(resolution__icontains=search) |
|
||||
Q(submitter_email__icontains=search) |
|
||||
Q(assigned_to__email__icontains=search) |
|
||||
Q(ticketcustomfieldvalue__value__icontains=search) |
|
||||
Q(created__icontains=search) |
|
||||
Q(due_date__icontains=search)
|
||||
)
|
||||
|
||||
|
||||
def get_query(query, huser):
|
||||
# Prefilter the allowed tickets
|
||||
objects = cache.get(huser.user.email + query)
|
||||
if objects is not None:
|
||||
return objects
|
||||
tickets = huser.get_tickets_in_queues().select_related()
|
||||
query_params = query_from_base64(query)
|
||||
ticket_qs = apply_query(tickets, query_params)
|
||||
cache.set(huser.user.email + query, ticket_qs, timeout=3600)
|
||||
return ticket_qs
|
||||
|
||||
|
||||
ORDER_COLUMN_CHOICES = Choices(
|
||||
DATATABLES_ORDER_COLUMN_CHOICES = Choices(
|
||||
('0', 'id'),
|
||||
('2', 'priority'),
|
||||
('3', 'title'),
|
||||
@ -112,45 +82,132 @@ ORDER_COLUMN_CHOICES = Choices(
|
||||
)
|
||||
|
||||
|
||||
def query_tickets_by_args(objects, order_by, **kwargs):
|
||||
"""
|
||||
This function takes in a list of ticket objects from the views and throws it
|
||||
to the datatables on ticket_list.html. If a search string was entered, this
|
||||
function filters existing dataset on search string and returns a filtered
|
||||
filtered list. The `draw`, `length` etc parameters are for datatables to
|
||||
display meta data on the table contents. The returning queryset is passed
|
||||
to a Serializer called DatatablesTicketSerializer in serializers.py.
|
||||
"""
|
||||
draw = int(kwargs.get('draw', None)[0])
|
||||
length = int(kwargs.get('length', None)[0])
|
||||
start = int(kwargs.get('start', None)[0])
|
||||
search_value = kwargs.get('search[value]', None)[0]
|
||||
order_column = kwargs.get('order[0][column]', None)[0]
|
||||
order = kwargs.get('order[0][dir]', None)[0]
|
||||
def get_query_class():
|
||||
from django.conf import settings
|
||||
|
||||
order_column = ORDER_COLUMN_CHOICES[order_column]
|
||||
# django orm '-' -> desc
|
||||
if order == 'desc':
|
||||
order_column = '-' + order_column
|
||||
def _get_query_class():
|
||||
return __Query__
|
||||
return getattr(settings,
|
||||
'HELPDESK_QUERY_CLASS',
|
||||
_get_query_class)()
|
||||
|
||||
queryset = objects.all().order_by(order_by)
|
||||
total = queryset.count()
|
||||
|
||||
if search_value:
|
||||
queryset = queryset.filter(Q(id__icontains=search_value) |
|
||||
Q(priority__icontains=search_value) |
|
||||
Q(title__icontains=search_value) |
|
||||
Q(queue__title__icontains=search_value) |
|
||||
Q(status__icontains=search_value) |
|
||||
Q(created__icontains=search_value) |
|
||||
Q(due_date__icontains=search_value) |
|
||||
Q(assigned_to__email__icontains=search_value))
|
||||
class __Query__:
|
||||
def __init__(self, huser, base64query=None, query_params=None):
|
||||
self.huser = huser
|
||||
self.params = query_params if query_params else query_from_base64(base64query)
|
||||
self.base64 = base64query if base64query else query_to_base64(query_params)
|
||||
self.result = None
|
||||
|
||||
count = queryset.count()
|
||||
queryset = queryset.order_by(order_column)[start:start + length]
|
||||
return {
|
||||
'items': queryset,
|
||||
'count': count,
|
||||
'total': total,
|
||||
'draw': draw
|
||||
}
|
||||
def get_search_filter_args(self):
|
||||
search = self.params.get('search_string', '')
|
||||
return get_search_filter_args(search)
|
||||
|
||||
def __run__(self, queryset):
|
||||
"""
|
||||
Apply a dict-based set of filters & parameters to a queryset.
|
||||
|
||||
queryset is a Django queryset, eg MyModel.objects.all() or
|
||||
MyModel.objects.filter(user=request.user)
|
||||
|
||||
params is a dictionary that contains the following:
|
||||
filtering: A dict of Django ORM filters, eg:
|
||||
{'user__id__in': [1, 3, 103], 'title__contains': 'foo'}
|
||||
|
||||
search_string: A freetext search string
|
||||
|
||||
sorting: The name of the column to sort by
|
||||
"""
|
||||
for key in self.params['filtering'].keys():
|
||||
filter = {key: self.params['filtering'][key]}
|
||||
queryset = queryset.filter(**filter)
|
||||
queryset = queryset.filter(self.get_search_filter_args())
|
||||
sorting = self.params.get('sorting', None)
|
||||
if sorting:
|
||||
sortreverse = self.params.get('sortreverse', None)
|
||||
if sortreverse:
|
||||
sorting = "-%s" % sorting
|
||||
queryset = queryset.order_by(sorting)
|
||||
return queryset
|
||||
|
||||
def refresh_query(self):
|
||||
tickets = self.huser.get_tickets_in_queues().select_related()
|
||||
ticket_qs = self.__run__(tickets)
|
||||
cache.set(self.huser.user.email + self.base64, ticket_qs, timeout=3600)
|
||||
return ticket_qs
|
||||
|
||||
def get(self):
|
||||
# Prefilter the allowed tickets
|
||||
objects = cache.get(self.huser.user.email + self.base64)
|
||||
if objects is not None:
|
||||
return objects
|
||||
return self.refresh_query()
|
||||
|
||||
def get_datatables_context(self, **kwargs):
|
||||
"""
|
||||
This function takes in a list of ticket objects from the views and throws it
|
||||
to the datatables on ticket_list.html. If a search string was entered, this
|
||||
function filters existing dataset on search string and returns a filtered
|
||||
filtered list. The `draw`, `length` etc parameters are for datatables to
|
||||
display meta data on the table contents. The returning queryset is passed
|
||||
to a Serializer called DatatablesTicketSerializer in serializers.py.
|
||||
"""
|
||||
objects = self.get()
|
||||
order_by = '-date_created'
|
||||
draw = int(kwargs.get('draw', None)[0])
|
||||
length = int(kwargs.get('length', None)[0])
|
||||
start = int(kwargs.get('start', None)[0])
|
||||
search_value = kwargs.get('search[value]', None)[0]
|
||||
order_column = kwargs.get('order[0][column]', None)[0]
|
||||
order = kwargs.get('order[0][dir]', None)[0]
|
||||
|
||||
order_column = DATATABLES_ORDER_COLUMN_CHOICES[order_column]
|
||||
# django orm '-' -> desc
|
||||
if order == 'desc':
|
||||
order_column = '-' + order_column
|
||||
|
||||
queryset = objects.all().order_by(order_by)
|
||||
total = queryset.count()
|
||||
|
||||
if search_value:
|
||||
queryset = queryset.filter(get_search_filter_args(search_value))
|
||||
|
||||
count = queryset.count()
|
||||
queryset = queryset.order_by(order_column)[start:start + length]
|
||||
return {
|
||||
'data': DatatablesTicketSerializer(queryset, many=True).data,
|
||||
'recordsFiltered': count,
|
||||
'recordsTotal': total,
|
||||
'draw': draw
|
||||
}
|
||||
|
||||
def get_timeline_context(self):
|
||||
events = []
|
||||
|
||||
for ticket in self.get():
|
||||
for followup in ticket.followup_set.all():
|
||||
event = {
|
||||
'start_date': self.mk_timeline_date(followup.date),
|
||||
'text': {
|
||||
'headline': ticket.title + '<br/>' + followup.title,
|
||||
'text': (followup.comment if followup.comment else _('No text')) + '<br/> <a href="%s" class="btn" role="button">%s</a>' %
|
||||
(reverse('helpdesk:view', kwargs={'ticket_id': ticket.pk}), _("View ticket")),
|
||||
},
|
||||
'group': _('Messages'),
|
||||
}
|
||||
events.append(event)
|
||||
|
||||
return {
|
||||
'events': events,
|
||||
}
|
||||
|
||||
def mk_timeline_date(self, date):
|
||||
return {
|
||||
'year': date.year,
|
||||
'month': date.month,
|
||||
'day': date.day,
|
||||
'hour': date.hour,
|
||||
'minute': date.minute,
|
||||
'second': date.second,
|
||||
'second': date.second,
|
||||
}
|
||||
|
Reference in New Issue
Block a user