2018-04-25 19:23:55 +00:00
import shlex
2017-04-28 12:14:27 +00:00
from django . shortcuts import render , get_object_or_404 , redirect
2018-04-27 20:53:38 +00:00
from django . contrib . postgres . search import SearchVector , TrigramSimilarity
2017-10-08 20:39:23 +00:00
from django . http import Http404 , JsonResponse
2017-10-24 18:59:58 +00:00
from django . contrib . admin . models import LogEntry
2018-04-25 19:23:55 +00:00
from django_select2 . views import AutoResponseView
2018-04-27 20:53:38 +00:00
from django . db . models import Q
from django . db import connection
2018-04-25 19:23:55 +00:00
from storage . models import Item , Label
2016-09-29 20:20:10 +00:00
2017-02-16 01:01:36 +00:00
def apply_smart_search ( query , objects ) :
general_term = [ ]
filters = { }
for prop in shlex . split ( query ) :
if ' : ' not in prop :
general_term . append ( prop )
else :
key , value = prop . split ( ' : ' , 1 )
2018-04-27 20:53:38 +00:00
if key in [ ' owner ' , ' taken_by ' ] :
filters [ key + ' __username ' ] = value
elif hasattr ( Item , key ) :
2017-02-16 01:01:36 +00:00
filters [ key + ' __search ' ] = value
2017-02-16 15:14:37 +00:00
elif key == ' ancestor ' :
objects = Item . objects . get ( pk = value ) . get_children ( )
2017-02-16 01:01:36 +00:00
elif key == ' prop ' or value :
if key == ' prop ' :
2018-04-27 20:53:38 +00:00
key , _ , value = value . partition ( ' : ' )
if not value :
filters [ ' props__isnull ' ] = { key : False }
else :
filters [ ' props__contains ' ] = { key : value }
2017-02-16 01:01:36 +00:00
else :
# "Whatever:"
general_term . append ( prop )
objects = objects . filter ( * * filters )
2018-04-27 20:53:38 +00:00
if not general_term :
return objects
objects = objects . annotate (
search = SearchVector ( ' name ' , ' description ' , ' props ' , config = ' simple ' ) ,
)
general_term = ' ' . join ( general_term )
objects = objects . annotate (
similarity = TrigramSimilarity ( ' name ' , general_term )
) . filter (
similarity__gte = 0.15
) . order_by ( ' -similarity ' )
2017-02-16 01:01:36 +00:00
return objects
2018-04-25 19:23:55 +00:00
2017-02-16 01:01:36 +00:00
def index ( request ) :
return render ( request , ' index.html ' )
2018-04-25 19:23:55 +00:00
2017-02-16 01:01:36 +00:00
def search ( request ) :
query = request . GET . get ( ' q ' , ' ' )
2018-04-27 20:53:38 +00:00
results = apply_smart_search ( query , Item . objects ) . all ( )
2017-12-13 19:02:55 +00:00
2018-04-27 20:53:38 +00:00
if results and len ( results ) == 1 or getattr ( results [ 0 ] , ' similarity ' , 0 ) == 1 :
return redirect ( results [ 0 ] )
2017-12-13 19:02:55 +00:00
2017-02-16 01:01:36 +00:00
return render ( request , ' results.html ' , {
' query ' : query ,
2018-04-27 20:53:38 +00:00
' results ' : results ,
2017-02-16 01:01:36 +00:00
} )
2018-04-25 19:23:55 +00:00
2017-02-16 01:01:36 +00:00
def item_display ( request , pk ) :
if not pk :
return render ( request , ' results.html ' , {
' results ' : Item . get_roots ( )
} )
item = get_object_or_404 ( Item , pk = pk )
return render ( request , ' item.html ' , {
' item ' : item ,
2017-10-24 18:59:08 +00:00
' categories ' : item . categories . all ( ) ,
2017-10-09 14:18:06 +00:00
' props ' : sorted ( item . props . items ( ) ) ,
2017-02-28 23:16:10 +00:00
' images ' : item . images . all ( ) ,
2017-04-28 12:14:27 +00:00
' labels ' : item . labels . all ( ) ,
2017-10-24 18:59:58 +00:00
' history ' : LogEntry . objects . filter ( object_id = item . pk ) ,
2017-02-16 01:01:36 +00:00
' ancestors ' : item . get_ancestors ( ) ,
2017-10-24 18:59:08 +00:00
' children ' : item . get_children ( ) . prefetch_related ( ' categories ' ) ,
2017-02-16 01:01:36 +00:00
} )
2017-04-28 12:14:27 +00:00
2018-04-25 19:23:55 +00:00
2017-04-28 12:14:27 +00:00
def label_lookup ( request , pk ) :
label = get_object_or_404 ( Label , pk = pk )
return redirect ( label . item )
2017-10-08 20:39:23 +00:00
2018-04-25 19:23:55 +00:00
2017-10-08 20:39:23 +00:00
class ItemSelectView ( AutoResponseView ) :
def get ( self , request , * args , * * kwargs ) :
self . widget = self . get_widget_or_404 ( )
self . term = kwargs . get ( ' term ' , request . GET . get ( ' term ' , ' ' ) )
self . object_list = self . get_queryset ( )
context = self . get_context_data ( )
return JsonResponse ( {
' results ' : [
{
' text ' : obj . name ,
' path ' : [ o . name for o in obj . get_ancestors ( ) ] ,
' id ' : obj . pk ,
}
for obj in context [ ' object_list ' ]
] ,
' more ' : context [ ' page_obj ' ] . has_next ( )
} )
2018-04-27 20:53:38 +00:00
class PropSelectView ( AutoResponseView ) :
def get ( self , request , * args , * * kwargs ) :
# self.widget = self.get_widget_or_404()
self . term = kwargs . get ( ' term ' , request . GET . get ( ' term ' , ' ' ) )
# context = self.get_context_data()
with connection . cursor ( ) as c :
c . execute ( " select e from (select skeys(props) as e, count(skeys(props)) as e_count from storage_item group by e order by e_count desc) as xD where e like %s limit 10; " , [ ' % ' + self . term + ' % ' ] )
props = c . fetchall ( )
return JsonResponse ( {
' results ' : [
{
' text ' : p ,
' id ' : p ,
}
for p in props
] ,
} )