spejstore/storage/views.py

181 lines
5.4 KiB
Python
Raw Permalink Normal View History

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
2019-02-02 12:21:15 +00:00
from django.http import Http404, JsonResponse, HttpResponse
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 import connection
2018-04-27 22:06:06 +00:00
from django.db.models import Q
2018-04-25 19:23:55 +00:00
from storage.models import Item, Label
2019-02-02 12:21:15 +00:00
from django.contrib.auth.decorators import login_required
from rest_framework.authtoken.models import Token
2016-09-29 20:20:10 +00:00
2023-07-11 13:34:35 +00:00
def apply_smart_search(query, objects):
general_term = []
filters = {}
for prop in shlex.split(query):
2023-07-11 13:34:35 +00:00
if ":" not in prop:
general_term.append(prop)
else:
2023-07-11 13:34:35 +00:00
key, value = prop.split(":", 1)
if key in ["owner", "taken_by"]:
filters[key + "__username"] = value
2018-04-27 20:53:38 +00:00
elif hasattr(Item, key):
2023-07-11 13:34:35 +00:00
filters[key + "__search"] = value
elif key == "ancestor":
objects = Item.objects.get(pk=value).get_children()
2023-07-11 13:34:35 +00:00
elif key == "prop" or value:
if key == "prop":
key, _, value = value.partition(":")
2018-04-27 20:53:38 +00:00
if not value:
2023-07-11 13:34:35 +00:00
filters["props__isnull"] = {key: False}
2018-04-27 20:53:38 +00:00
else:
2023-07-11 13:34:35 +00:00
filters["props__contains"] = {key: value}
else:
# "Whatever:"
general_term.append(prop)
objects = objects.filter(**filters)
2018-04-27 20:53:38 +00:00
if not general_term:
return objects
2023-07-11 13:34:35 +00:00
general_term = " ".join(general_term)
objects = (
objects.annotate(
search=SearchVector("name", "description", "props", config="simple"),
similarity=TrigramSimilarity("name", general_term),
)
.filter(Q(similarity__gte=0.15) | Q(search__contains=general_term))
.order_by("-similarity")
)
return objects
2018-04-25 19:23:55 +00:00
def index(request):
2023-07-11 14:19:27 +00:00
# get_roots was removed, so we're doing it this way now.
return render(
request, "results.html", {"results": Item.objects.filter(**{"path__level": 1})}
)
2018-04-25 19:23:55 +00:00
def search(request):
2023-07-11 13:34:35 +00:00
query = request.GET.get("q", "")
2018-04-27 20:53:38 +00:00
results = apply_smart_search(query, Item.objects).all()
2023-07-11 13:34:35 +00:00
if results and (len(results) == 1 or getattr(results[0], "similarity", 0) == 1):
2018-04-27 20:53:38 +00:00
return redirect(results[0])
2023-07-11 13:34:35 +00:00
return render(
request,
"results.html",
{
"query": query,
"results": results,
},
)
2018-04-25 19:23:55 +00:00
def item_display(request, pk):
if not pk:
2020-05-11 19:25:35 +00:00
return index(request)
item = get_object_or_404(Item, pk=pk)
2020-05-11 18:09:02 +00:00
labels = item.labels.all()
has_one_label = len(labels) == 1
2023-07-11 13:34:35 +00:00
return render(
request,
"item.html",
{
"title": item.name,
"item": item,
"categories": item.categories.all(),
"props": sorted(item.props.items()),
"images": item.images.all(),
"labels": labels,
"has_one_label": has_one_label,
"history": LogEntry.objects.filter(object_id=item.pk),
"ancestors": item.get_ancestors(),
"children": item.get_children().prefetch_related("categories"),
},
)
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):
try:
label = Label.objects.get(pk=pk)
return redirect(label.item)
except Label.DoesNotExist:
try:
# look up by short id
item = Item.objects.get(uuid__startswith=pk)
return redirect(item)
except Item.DoesNotExist:
raise Http404("Very sad to say, I could not find this thing")
2018-04-25 19:23:55 +00:00
2019-02-02 12:21:15 +00:00
def apitoken(request):
print(Token)
token, created = Token.objects.get_or_create(user=request.user)
2023-07-11 13:34:35 +00:00
return HttpResponse(token.key, content_type="text/plain")
2019-02-02 12:21:15 +00:00
class ItemSelectView(AutoResponseView):
def get(self, request, *args, **kwargs):
self.widget = self.get_widget_or_404()
2023-07-11 13:34:35 +00:00
self.term = kwargs.get("term", request.GET.get("term", ""))
2018-04-28 18:44:47 +00:00
self.object_list = apply_smart_search(self.term, Item.objects)
context = self.get_context_data()
2023-07-11 13:34:35 +00:00
return JsonResponse(
{
"results": [
{
"text": obj.name,
"path": [o.name for o in obj.get_ancestors()],
"id": obj.pk,
}
for obj in context["object_list"]
],
2023-07-11 13:34:35 +00:00
"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()
2023-07-11 13:34:35 +00:00
self.term = kwargs.get("term", request.GET.get("term", ""))
2018-04-27 20:53:38 +00:00
# context = self.get_context_data()
with connection.cursor() as c:
2023-07-11 13:34:35 +00:00
c.execute(
"""
2018-10-10 18:37:30 +00:00
SELECT key, count(*) FROM
(SELECT (each(props)).key FROM storage_item) AS stat
WHERE key like %s
GROUP BY key
ORDER BY count DESC, key
limit 10;
2023-07-11 13:34:35 +00:00
""",
["%" + self.term + "%"],
)
2018-09-26 20:20:16 +00:00
props = [e[0] for e in c.fetchall()]
2023-07-11 13:34:35 +00:00
return JsonResponse(
{
"results": [
{
"text": p,
"id": p,
}
for p in props
2018-04-27 20:53:38 +00:00
],
2023-07-11 13:34:35 +00:00
}
)