From a91b98c5ac8624f38be998958c1773e7e4a83ba2 Mon Sep 17 00:00:00 2001 From: Junwei Zhao Date: Sun, 8 Sep 2024 18:50:01 +1000 Subject: [PATCH] Add search --- db.sqlite3 | Bin 147456 -> 147456 bytes links/__pycache__/urls.cpython-312.pyc | Bin 1142 -> 1142 bytes links/__pycache__/views.cpython-312.pyc | Bin 5386 -> 7110 bytes links/search_urls.py | 6 + links/urls.py | 2 +- links/views.py | 34 ++++- locale/zh_Hans/LC_MESSAGES/django.mo | Bin 1179 -> 1675 bytes locale/zh_Hans/LC_MESSAGES/django.po | 3 + templates/base.html | 134 ++++++++++++++++++- url_manager/__pycache__/urls.cpython-312.pyc | Bin 567 -> 667 bytes url_manager/urls.py | 6 +- 11 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 links/search_urls.py diff --git a/db.sqlite3 b/db.sqlite3 index ff301270bbbc582fb8637686e574e748779d1118..82f93f51e1830d0bd9b222a657cdc13fb0876275 100644 GIT binary patch delta 563 zcmZo@;B08%oFL6;F;T{u(PCqQs6HdhuO3@ofnOsz~U^(;(GjV(-A zr_beQN(X9u$-w`c|11A{{+B?FH~HCEnHd>bS*E|2XA%`)*JNQjFnZ+5wVavh6EXoK93U)STLB=v8HeP0VFux=t SGcTQ$m6@Nhj0HrdGXntTx{lod delta 181 zcmZo@;B08%oFL6;JWu?LKW%4biY|&eMKACyh zE~zDnnK@yZspUm{KrNG_n4e7k#4IDzAvZ(xx}@<%N#hGv0asW8Kk#$#Gc|G-NdOfA E0JkO}&j0`b delta 102 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/', views.LinkUpdateView.as_view(), name='link_update'), path('delete//', views.LinkDeleteView.as_view(), name='link_delete'), path('delete-selected/', views.delete_selected, name='delete_selected'), - path('/', views.redirect_to_original, name='redirect_to_original'), path('detail//', views.LinkDetailView.as_view(), name='link_detail'), + path('/', views.redirect_to_original, name='redirect_to_original'), ] diff --git a/links/views.py b/links/views.py index b682c49..78f79e4 100644 --- a/links/views.py +++ b/links/views.py @@ -1,7 +1,7 @@ from django.shortcuts import render, redirect, get_object_or_404 from django.views.generic import ListView, CreateView, UpdateView, DeleteView, DetailView -from django.urls import reverse_lazy -from django.db.models import F, Count +from django.urls import reverse_lazy, reverse # Add 'reverse' here +from django.db.models import F, Count, Q from django.db.models.functions import TruncDate from .models import Link, ClickLog from .forms import LinkForm @@ -11,6 +11,7 @@ from django.contrib import messages from django.db import IntegrityError from django.utils.translation import gettext as _ from django.core.exceptions import ValidationError +from django.http import JsonResponse class LinkListView(ListView): model = Link @@ -79,3 +80,32 @@ class LinkDetailView(DetailView): context['click_stats'] = json.dumps(click_stats_list, cls=DjangoJSONEncoder) return context + +def search_aliases(request): + query = request.GET.get('q', '').strip() + print(f"Search query: {query}") # Debug print + + if not query: + return JsonResponse([], safe=False) + + if len(query) == 1: + # For single-letter queries, only match the start of the alias + links = Link.objects.filter(alias__istartswith=query)[:10] + else: + # For longer queries, keep the current behavior + links = Link.objects.filter(Q(alias__icontains=query) | Q(original_url__icontains=query))[:10] + + print(f"Found {links.count()} links") # Debug print + + results = [] + for link in links: + try: + url = request.build_absolute_uri(reverse('redirect_to_original', args=[link.alias])) + results.append({'alias': link.alias, 'url': url}) + print(f"Added result: {link.alias}") # Debug print + except Exception as e: + print(f"Error creating URL for alias {link.alias}: {str(e)}") # Debug print + continue + + print(f"Search results: {results}") # Debug print + return JsonResponse(results, safe=False) diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index be0e1d8394bb7a0d70a6c324ab65cb0d6ad6078f..67b041e66229df39226d9f683937fad5c220fa24 100644 GIT binary patch delta 1063 zcmXYuO=uHQ5XWC?jK*3&T0d$l_zo&sFrc6!3L>=!v7n^wMUc8Aujbh`soh2Fr499? z4Yeg2n%WQ1h?V-0w$@-%qrG?$5%es@i`m@-Ja`aK9{f-82Il>CX5P%a*_reXRrUR- zc8@YhJ#;7Z4|EUoiwg(jQUzmcKn+|CO0WTpfF5uH+ythSy`bzRa3lPm!FAww6}OcC z7l^uj>>obdxZqyJm>2Yd)UXCz57sO0Q}M%KHT)-)-w#rLJGdDPs`z#A80;8Gbv}ZX z;5YC%hFbwW=+9~~7EQ7X+zswk_F0e;{fh01I!KfCC_4sHep2}#Dm$&10jW+-*`JjC zm5BaqMLCKfP4*Wo{Rvd1!ZkRkVI4??8o(pqQRNRSe=n%E#?~TEe}g6_p+CAEiqZ^& zm+H~VHE2n8;H-txE=i~nHdB%+oV3Gj(5)p89tGB^Zvs7-9#2B+*Z|!E^(4}+GnKr> z)J$oZGGHWryY^pb>=v3Sg8Y=pP77U_LV>ry3Lpa8)TC~(rl2%S2XB_)PSzB@tV<)r znl;1ZZCydC!YIO3LgGZl!7D=R4urU-OU)35&*x(;@@khZJ0w~*hGbY6g0+UEQNDr` z&k6Q$aRW~@eEhsFkjMj}NCeP$Pc0EH#Yrpo&K`SP9Lq3k@NsecsX{Rt%V*QY)DkPqJ+p7#X3qO$VfmgyF|llqOtZq! z>%v@`*;7#~K4MR1?BqNvhssHbbM8ae?D&+Ed14K|wBo}wnll^Ce@LLXog6^%>2kzc zT(Hs)tf`rw(f-2RBHG(S&-2-6KKmk{9k$|korzoJo4CO2XwKVKY>=)!rwd)|5P-g9r>bL!UKea;iY@F9i}mxy7+tPKy0 zYuFB}&;@I796rG|_$mE@eaOFIFLc{m^?t~?A39+W@_N(IO{CErCcOC)?1meVKa9)w zD(ph8!5J)`hrIE#qvZ=6MgAu9AIR(2un5}&xq(5*|4qm|WaS#syevc@|F8nNp(sR$ zl#=xwS>Kf&Li9tO2p-m{ThqU%N6z>FUPK3i_dt(UGZe(+|KKa;&9OH1Ao!|qVC!lD zksh^2^jmu%uqafK5!AxJhHNtF!{-C4$QP`*T)n%hn LGLH5d#S8icZfIJa diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index 62ffad6..c74f259 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -93,6 +93,9 @@ msgstr "该别名已存在。请选择一个不同的别名。" msgid "Edit Link" msgstr "编辑链接" +msgid "Search aliases..." +msgstr "搜索别名..." + #: 3.12/lib/python3.12/site-packages/django/forms/fields.py:95 msgid "This field is required." msgstr "" diff --git a/templates/base.html b/templates/base.html index 78a5958..e62b126 100644 --- a/templates/base.html +++ b/templates/base.html @@ -32,13 +32,36 @@ border-color: #f5c6cb; color: #721c24; } + .search-results { + position: absolute; + top: 100%; + left: 0; + right: 0; + background-color: white; + border: 1px solid #ddd; + border-top: none; + max-height: 300px; + overflow-y: auto; + display: none; + } + .search-result-item { + padding: 10px; + cursor: pointer; + } + .search-result-item:hover, .search-result-item.active { + background-color: #f8f9fa; + }