From 5dd381c44d847d812c4e120dd2d1f057dc1bf546 Mon Sep 17 00:00:00 2001 From: sosokker Date: Sun, 17 Sep 2023 15:07:53 +0700 Subject: [PATCH] Add search --- polls/forms.py | 9 ++- polls/templates/polls/index.html | 2 +- polls/templates/polls/search.html | 110 ++++++++++++++++++++++++++++++ polls/tests/test_search_poll.py | 25 +++++++ polls/urls.py | 1 + polls/views.py | 16 ++++- 6 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 polls/templates/polls/search.html create mode 100644 polls/tests/test_search_poll.py diff --git a/polls/forms.py b/polls/forms.py index ffdf2f8..a6deff7 100644 --- a/polls/forms.py +++ b/polls/forms.py @@ -37,4 +37,11 @@ class SignUpForm(UserCreationForm): error_messages = { 'password_mismatch': "The two password fields didn't match.", - } \ No newline at end of file + } + + +class PollSearchForm(forms.Form): + q = forms.CharField() + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) diff --git a/polls/templates/polls/index.html b/polls/templates/polls/index.html index 0dd54a0..44b75e5 100644 --- a/polls/templates/polls/index.html +++ b/polls/templates/polls/index.html @@ -19,7 +19,7 @@
-
+
🔎
diff --git a/polls/templates/polls/search.html b/polls/templates/polls/search.html new file mode 100644 index 0000000..3eba8bd --- /dev/null +++ b/polls/templates/polls/search.html @@ -0,0 +1,110 @@ +{% extends "polls/base.html" %} + +{% block content %} + + + +
+ {% if q %} + {% with results.count as total_result %} +

Found {{ total_result }} Polls!

+ {% endwith %} + {% endif %} +
+
+ {% for question in results %} +
+ +
+

{{ question.question_text }}

+
+

{{ question.short_description }}

+
+ 👍 + {{ question.up_vote_percentage }}% Upvoted + + 👎 + {{ question.down_vote_percentage }}% Downvoted +
+ +
+ 🕒 {{ question.time_left }} + {{ question.participants }} Participants 👤 +
+
+ + +
+
+ {% if forloop.counter|divisibleby:2 %} +
+
+ {% else %} +
+
+ {% endif %} +
+ {% endfor %} +
+
+ +
+ +{% endblock content %} \ No newline at end of file diff --git a/polls/tests/test_search_poll.py b/polls/tests/test_search_poll.py new file mode 100644 index 0000000..1340965 --- /dev/null +++ b/polls/tests/test_search_poll.py @@ -0,0 +1,25 @@ +from django.test import TestCase +from django.urls import reverse + +from ..models import Question +from ..views import search_poll + + +class SearchPollTest(TestCase): + """Test if user search with normal string. It must return same queryset as filter question objects""" + def test_search_normal_poll(self): + data_1 = {'q': 'what'} + data_2 = {'q': 'prefer'} + q_1 = 'what' + q_2 = 'prefer' + response_1 = self.client.get(reverse("polls:search_poll"), data_1) + response_2 = self.client.get(reverse("polls:search_poll"), data_2) + self.assertQuerysetEqual(response_1.context['results'], Question.objects.filter(question_text__icontains=q_1)) + self.assertQuerysetEqual(response_2.context['results'], Question.objects.filter(question_text__icontains=q_2)) + + def test_search_with_empty(self): + """Test if user search with empty string. It must return all question""" + data = {'q': ''} + response = self.client.get(reverse("polls:search_poll"), data) + self.assertQuerysetEqual(response.context['results'], Question.objects.all()) + diff --git a/polls/urls.py b/polls/urls.py index 7b0b4fa..3eb16ce 100644 --- a/polls/urls.py +++ b/polls/urls.py @@ -11,4 +11,5 @@ urlpatterns = [ path("signup/", views.SignUpView.as_view(), name="signup"), path("upvote/", views.up_down_vote, {'vote_type' : 'upvote'}, name="upvote"), path("downvote/", views.up_down_vote, {'vote_type' : 'downvote'}, name="downvote"), + path("search", views.search_poll, name="search_poll"), ] diff --git a/polls/views.py b/polls/views.py index e58f1f1..1e3f7df 100644 --- a/polls/views.py +++ b/polls/views.py @@ -12,7 +12,7 @@ from django.contrib.auth import authenticate, login from django.contrib.auth.decorators import login_required from django.db.models import Q -from .forms import SignUpForm +from .forms import SignUpForm, PollSearchForm from .models import Choice, Question, Vote @@ -189,3 +189,17 @@ def get_client_ip(request): else: ip = request.META.get('REMOTE_ADDR') return ip + +def search_poll(request): + form = PollSearchForm + + results = [] + q = '' + if 'q' in request.GET: + form = PollSearchForm(request.GET) + if form.is_valid(): + q = form.cleaned_data['q'] + results = Question.objects.filter(question_text__icontains=q) + if q == '': + results = Question.objects.all() + return render(request, 'polls/search.html', {'form':form, 'results':results, 'q':q}) \ No newline at end of file