Format file according to flake8

This commit is contained in:
sosokker 2023-09-18 00:11:35 +07:00
parent c81dea9a14
commit f97a772bf3
16 changed files with 114 additions and 91 deletions

12
.flake8 Normal file
View File

@ -0,0 +1,12 @@
[flake8]
max-line-length = 120
exclude=
migrations
mysite
logs
.venv
apps.py
setup.py
per-file-ignores =
.\polls\tests\test_sentiment_model.py: E501
.\polls\models.py: F811

View File

@ -17,12 +17,13 @@ class QuestionAdmin(admin.ModelAdmin):
("Long Description", {"fields": ["long_description"], "classes": ["collapse"]}), ("Long Description", {"fields": ["long_description"], "classes": ["collapse"]}),
("Add Tag", {"fields": ["tags"], "classes": ["collapse"]}) ("Add Tag", {"fields": ["tags"], "classes": ["collapse"]})
] ]
list_display = ["question_text", "pub_date", "end_date", "was_published_recently", "can_vote", "trending_score", "get_tags"] list_display = ["question_text", "pub_date", "end_date", "was_published_recently", "can_vote",
"trending_score", "get_tags"]
inlines = [ChoiceInline] inlines = [ChoiceInline]
list_filter = ["pub_date", "end_date"] list_filter = ["pub_date", "end_date"]
search_fields = ["question_text"] search_fields = ["question_text"]
# https://stackoverflow.com/questions/10904848/adding-inline-many-to-many-objects-in-django-admin # https://stackoverflow.com/questions/10904848/adding-inline-many-to-many-objects-in-django-admin
admin.site.register(Question, QuestionAdmin) admin.site.register(Question, QuestionAdmin)
admin.site.register(Tag) # Add Field to modify tags objects in Question admin.site.register(Tag) # Add Field to modify tags objects in Question

View File

@ -4,6 +4,7 @@ from django.apps import AppConfig
class PollsConfig(AppConfig): class PollsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = 'django.db.models.BigAutoField'
name = 'polls' name = 'polls'
def ready(self) -> None: def ready(self) -> None:
import polls.signals import polls.signals

View File

@ -7,18 +7,19 @@ from django.contrib.auth.models import User
from .models import Question, Tag from .models import Question, Tag
class SignUpForm(UserCreationForm): class SignUpForm(UserCreationForm):
tailwind_class = "w-full border-2 border-gray-300 bg-gray-100 rounded-lg focus:ring focus:border-blue-300 focus:shadow-none" tailwind_class = """w-full border-2 border-gray-300 bg-gray-100 rounded-lg
focus:ring focus:border-blue-300 focus:shadow-none"""
logger = logging.getLogger('signup_form') logger = logging.getLogger('signup_form')
username = forms.CharField(widget=forms.TextInput(attrs={'class': tailwind_class}), username = forms.CharField(widget=forms.TextInput(attrs={'class': tailwind_class}), error_messages={
error_messages={ 'unique': 'This username is already in use.',
'unique': 'This username is already in use.', 'invalid': 'Invalid username format.',
'invalid': 'Invalid username format.', 'max_length': 'Username should not exceed 150 characters.',
'max_length': 'Username should not exceed 150 characters.',
} }
) )
password1 = forms.CharField(widget=forms.PasswordInput(attrs={'class': tailwind_class}), password1 = forms.CharField(widget=forms.PasswordInput(attrs={'class': tailwind_class}),
error_messages={'min_length': 'Password must contain at least 8 characters.',} error_messages={'min_length': 'Password must contain at least 8 characters.', }
) )
password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class': tailwind_class}),) password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class': tailwind_class}),)
@ -49,15 +50,24 @@ class PollSearchForm(forms.Form):
class PollCreateForm(forms.ModelForm): class PollCreateForm(forms.ModelForm):
box_style = "w-full py-2 px-2 border-2 border-gray-300 bg-gray-100 rounded-lg focus:ring focus:border-blue-300 focus:shadow-none" box_style = """w-full py-2 px-2 border-2 border-gray-300 bg-gray-100 rounded-lg
large_box_style = "w-full border-2 border-gray-300 bg-gray-100 rounded-lg focus:ring focus:border-blue-300 focus:shadow-none" focus:ring focus:border-blue-300 focus:shadow-none"""
large_box_style = """w-full border-2 border-gray-300 bg-gray-100 rounded-lg
focus:ring focus:border-blue-300 focus:shadow-none"""
question_text = forms.CharField(min_length=10, max_length=100, required=True, question_text = forms.CharField(min_length=10, max_length=100, required=True,
widget=forms.TextInput(attrs={'class':box_style, 'placeholder':"What is your question?"})) widget=forms.TextInput(attrs={'class': box_style,
'placeholder': "What is your question?"}))
pub_date = forms.DateTimeField(widget=forms.DateInput(attrs={'type': 'date'})) pub_date = forms.DateTimeField(widget=forms.DateInput(attrs={'type': 'date'}))
end_date = forms.DateTimeField(widget=forms.DateInput(attrs={'type': 'date'})) end_date = forms.DateTimeField(widget=forms.DateInput(attrs={'type': 'date'}))
short_description = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class':box_style, 'placeholder':"Short description (Maximum 200 characters)"})) short_description = forms.CharField(max_length=200,
long_description = forms.CharField(max_length=2000, widget=forms.Textarea(attrs={'class':large_box_style, 'placeholder':"Long description (Maximum 2000 characters)"})) widget=forms.TextInput(
attrs={'class': box_style,
'placeholder': "Short description (Maximum 200 characters)"}))
long_description = forms.CharField(max_length=2000,
widget=forms.Textarea(
attrs={'class': large_box_style,
'placeholder': "Long description (Maximum 2000 characters)"}))
tags = forms.MultipleChoiceField( tags = forms.MultipleChoiceField(
choices=[(tag.id, tag.tag_text) for tag in Tag.objects.all()], choices=[(tag.id, tag.tag_text) for tag in Tag.objects.all()],
widget=forms.CheckboxSelectMultiple, widget=forms.CheckboxSelectMultiple,
@ -69,7 +79,7 @@ class PollCreateForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
class Meta: class Meta:
model = Question model = Question
fields = ['question_text', 'pub_date', 'end_date', 'short_description', 'long_description', 'tags'] fields = ['question_text', 'pub_date', 'end_date', 'short_description', 'long_description', 'tags']

View File

@ -12,7 +12,6 @@ Attributes:
from django.db import models, IntegrityError from django.db import models, IntegrityError
from django.utils import timezone from django.utils import timezone
from django.contrib import admin from django.contrib import admin
from django.db.models import Sum
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -169,7 +168,7 @@ class Question(models.Model):
self.save() self.save()
except IntegrityError: except IntegrityError:
vote = self.sentimentvote_set.filter(user=user) vote = self.sentimentvote_set.filter(user=user)
if vote[0].vote_types == False: if vote[0].vote_types is False:
vote.update(vote_types=True) vote.update(vote_types=True)
self.save() self.save()
else: else:
@ -185,7 +184,7 @@ class Question(models.Model):
self.save() self.save()
except IntegrityError: except IntegrityError:
vote = self.sentimentvote_set.filter(user=user) vote = self.sentimentvote_set.filter(user=user)
if vote[0].vote_types == True: if vote[0].vote_types is True:
vote.update(vote_types=False) vote.update(vote_types=False)
self.save() self.save()
else: else:
@ -207,8 +206,8 @@ class Question(models.Model):
published_date_duration = timezone.now() - self.pub_date published_date_duration = timezone.now() - self.pub_date
score = 0 score = 0
if (published_date_duration.seconds < 259200): # Second unit if (published_date_duration.seconds < 259200): # Second unit
score += 100 score += 100
elif (published_date_duration.seconds < 604800): elif (published_date_duration.seconds < 604800):
score += 75 score += 75
elif (published_date_duration.seconds < 2592000): elif (published_date_duration.seconds < 2592000):
@ -216,7 +215,7 @@ class Question(models.Model):
else: else:
score += 25 score += 25
if (up == None) and (down == None): if (up is None) and (down is None):
score += ((self.up_vote_count/5) - (self.down_vote_count/5)) * 100 score += ((self.up_vote_count/5) - (self.down_vote_count/5)) * 100
else: else:
score += ((up/5) - (down/5)) * 100 score += ((up/5) - (down/5)) * 100
@ -226,10 +225,10 @@ class Question(models.Model):
def get_tags(self, *args, **kwargs): def get_tags(self, *args, **kwargs):
return "-".join([tag.tag_text for tag in self.tags.all()]) return "-".join([tag.tag_text for tag in self.tags.all()])
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"""Modify save method of Question object""" """Modify save method of Question object"""
# to-be-added instance # * https://github.com/django/django/blob/866122690dbe233c054d06f6afbc2f3cc6aea2f2/django/db/models/base.py#L447 # to-be-added instance
# * https://github.com/django/django/blob/866122690dbe233c054d06f6afbc2f3cc6aea2f2/django/db/models/base.py#L447
if self._state.adding: if self._state.adding:
try: try:
self.trend_score = self.trending_score() self.trend_score = self.trending_score()
@ -271,7 +270,7 @@ class Vote(models.Model):
def __str__(self): def __str__(self):
return f"{self.user} voted for {self.choice} in {self.question}" return f"{self.user} voted for {self.choice} in {self.question}"
# ! Most of the code from https://stackoverflow.com/a/70869267 # ! Most of the code from https://stackoverflow.com/a/70869267
class SentimentVote(models.Model): class SentimentVote(models.Model):
@ -296,4 +295,4 @@ class SentimentVote(models.Model):
unique_together (list of str): Ensures that a user can only cast one sentiment vote (upvote or downvote) unique_together (list of str): Ensures that a user can only cast one sentiment vote (upvote or downvote)
for a specific question. for a specific question.
""" """
unique_together = ['user', 'question'] unique_together = ['user', 'question']

View File

@ -4,6 +4,7 @@ from django.dispatch import receiver
log = logging.getLogger("django") log = logging.getLogger("django")
def get_client_ip(request): def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for: if x_forwarded_for:
@ -12,9 +13,10 @@ def get_client_ip(request):
ip = request.META.get('REMOTE_ADDR') ip = request.META.get('REMOTE_ADDR')
return ip return ip
#! https://stackoverflow.com/questions/37618473/how-can-i-log-both-successful-and-failed-login-and-logout-attempts-in-django
# !https://stackoverflow.com/questions/37618473/how-can-i-log-both-successful-and-failed-login-and-logout-attempts-in-django
@receiver(user_logged_in) @receiver(user_logged_in)
def user_logged_in_callback(sender, request, user, **kwargs): def user_logged_in_callback(sender, request, user, **kwargs):
ip = get_client_ip(request) ip = get_client_ip(request)
log.info('Login User: {user} via ip: {ip}'.format( log.info('Login User: {user} via ip: {ip}'.format(
@ -22,8 +24,9 @@ def user_logged_in_callback(sender, request, user, **kwargs):
ip=ip ip=ip
)) ))
@receiver(user_logged_out) @receiver(user_logged_out)
def user_logged_out_callback(sender, request, user, **kwargs): def user_logged_out_callback(sender, request, user, **kwargs):
ip = get_client_ip(request) ip = get_client_ip(request)
log.info('Logout User: {user} via ip: {ip}'.format( log.info('Logout User: {user} via ip: {ip}'.format(
@ -31,8 +34,9 @@ def user_logged_out_callback(sender, request, user, **kwargs):
ip=ip ip=ip
)) ))
@receiver(user_login_failed) @receiver(user_login_failed)
def user_login_failed_callback(sender, credentials, **kwargs): def user_login_failed_callback(sender, credentials, **kwargs):
log.warning('Login Failed for: {credentials}'.format( log.warning('Login Failed for: {credentials}'.format(
credentials=credentials, credentials=credentials,
)) ))

View File

@ -1,7 +1,6 @@
from django.utils import timezone from django.utils import timezone
from django.contrib.auth.models import User
from ..models import Question, Vote, Choice from ..models import Question
def create_question(question_text, day=0): def create_question(question_text, day=0):
@ -11,4 +10,4 @@ def create_question(question_text, day=0):
in the past, positive for questions that have yet to be published). in the past, positive for questions that have yet to be published).
""" """
time = timezone.now() + timezone.timedelta(days=day) time = timezone.now() + timezone.timedelta(days=day)
return Question.objects.create(question_text=question_text, pub_date=time) return Question.objects.create(question_text=question_text, pub_date=time)

View File

@ -1,5 +1,4 @@
from django.test import TestCase, Client from django.test import TestCase, Client
from django.utils import timezone
from django.urls import reverse from django.urls import reverse
from django.contrib.auth.models import User from django.contrib.auth.models import User

View File

@ -102,4 +102,4 @@ class QuestionModelTests(TestCase):
pub_date = timezone.now() - datetime.timedelta(hours=1) pub_date = timezone.now() - datetime.timedelta(hours=1)
end_date = timezone.now() + datetime.timedelta(hours=2) end_date = timezone.now() + datetime.timedelta(hours=2)
question = Question(pub_date=pub_date, end_date=end_date) question = Question(pub_date=pub_date, end_date=end_date)
self.assertIs(question.can_vote(), True) self.assertIs(question.can_vote(), True)

View File

@ -2,7 +2,6 @@ from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from ..models import Question from ..models import Question
from ..views import search_poll
class SearchPollTest(TestCase): class SearchPollTest(TestCase):
@ -22,4 +21,3 @@ class SearchPollTest(TestCase):
data = {'q': ''} data = {'q': ''}
response = self.client.get(reverse("polls:search_poll"), data) response = self.client.get(reverse("polls:search_poll"), data)
self.assertQuerysetEqual(response.context['results'], Question.objects.all()) self.assertQuerysetEqual(response.context['results'], Question.objects.all())

View File

@ -2,7 +2,7 @@ from django.test import TransactionTestCase, Client
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .base import create_question from .base import create_question
from ..views import up_down_vote
# ! https://stackoverflow.com/questions/24588520/testing-several-integrityerrors-in-the-same-django-unittest-test-case # ! https://stackoverflow.com/questions/24588520/testing-several-integrityerrors-in-the-same-django-unittest-test-case
# * https://stackoverflow.com/questions/44450533/difference-between-testcase-and-transactiontestcase-classes-in-django-test # * https://stackoverflow.com/questions/44450533/difference-between-testcase-and-transactiontestcase-classes-in-django-test
@ -32,11 +32,11 @@ class UpDownVoteViewTest(TransactionTestCase):
self.assertEqual(count_up, 0) self.assertEqual(count_up, 0)
self.assertEqual(count_down, 1) self.assertEqual(count_down, 1)
def test_can_change_up_to_down(self): def test_can_change_down_to_up(self):
self.client.login(username="test_user", password="12345abc") self.client.login(username="test_user", password="12345abc")
self.q1.downvote(self.user) self.q1.downvote(self.user)
self.q1.upvote(self.user) self.q1.upvote(self.user)
count_up = self.q1.sentimentvote_set.filter(vote_types=True).count() count_up = self.q1.sentimentvote_set.filter(vote_types=True).count()
count_down = self.q1.sentimentvote_set.filter(vote_types=False).count() count_down = self.q1.sentimentvote_set.filter(vote_types=False).count()
self.assertEqual(count_up, 1) self.assertEqual(count_up, 1)
self.assertEqual(count_down, 0) self.assertEqual(count_down, 0)

View File

@ -42,4 +42,4 @@ class SignUpTestCase(TestCase):
'password2': 'testpassword123', 'password2': 'testpassword123',
} }
response = self.client.post(signup_url, data) response = self.client.post(signup_url, data)
self.assertRedirects(response, reverse("polls:index")) self.assertRedirects(response, reverse("polls:index"))

View File

@ -5,6 +5,7 @@ from django.contrib.auth.models import User
from .base import create_question from .base import create_question
from ..models import Vote, Choice from ..models import Vote, Choice
class VoteViewTest(TestCase): class VoteViewTest(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -20,9 +21,9 @@ class VoteViewTest(TestCase):
""" """
self.client.login(username=self.user.username, password="aaa123321aaa") self.client.login(username=self.user.username, password="aaa123321aaa")
response = self.client.post(reverse("polls:vote", args=(self.question.id,)), response = self.client.post(reverse("polls:vote", args=(self.question.id,)),
{'choice' : self.choice1.id}) {'choice': self.choice1.id})
self.assertRedirects(response, reverse("polls:results", args=(self.question.id,))) self.assertRedirects(response, reverse("polls:results", args=(self.question.id,)))
self.assertTrue(Vote.objects.filter(user=self.user, question=self.question).exists()) self.assertTrue(Vote.objects.filter(user=self.user, question=self.question).exists())
@ -32,18 +33,18 @@ class VoteViewTest(TestCase):
""" """
self.client.login(username=self.user.username, password="aaa123321aaa") self.client.login(username=self.user.username, password="aaa123321aaa")
response = self.client.post(reverse("polls:vote", args=(self.question.id,)), response = self.client.post(reverse("polls:vote", args=(self.question.id,)),
{'choice' : 1000}) {'choice': 1000})
self.assertRedirects(response, reverse('polls:detail', args=(self.question.id,))) self.assertRedirects(response, reverse('polls:detail', args=(self.question.id,)))
def test_vote_without_login(self): def test_vote_without_login(self):
""" """
Test the vote view when the user is not logged in. Test the vote view when the user is not logged in.
""" """
response = self.client.post(reverse("polls:vote", args=(self.question.id,)), response = self.client.post(reverse("polls:vote", args=(self.question.id,)),
{'choice' : self.choice1}) {'choice': self.choice1})
self.assertRedirects(response, "/accounts/login/?next=/polls/1/vote/") self.assertRedirects(response, "/accounts/login/?next=/polls/1/vote/")
def test_vote_voting_not_allowed(self): def test_vote_voting_not_allowed(self):
@ -55,9 +56,8 @@ class VoteViewTest(TestCase):
self.question_2 = create_question(question_text="Test not allow", day=10) self.question_2 = create_question(question_text="Test not allow", day=10)
self.choice_2 = Choice.objects.create(question=self.question_2, choice_text="Test Choice 2_2") self.choice_2 = Choice.objects.create(question=self.question_2, choice_text="Test Choice 2_2")
response = self.client.post(reverse("polls:vote", args=(self.question_2.id,)), response = self.client.post(reverse("polls:vote", args=(self.question_2.id,)), {"choice": self.choice_2.id})
{"choice" : self.choice_2.id})
self.assertRedirects(response, reverse('polls:index')) self.assertRedirects(response, reverse('polls:index'))
def test_vote_with_no_post_data(self): def test_vote_with_no_post_data(self):
@ -81,6 +81,6 @@ class VoteViewTest(TestCase):
response_2 = self.client.post(reverse("polls:vote", args=(self.question.id,)), {"choice": self.choice2.id}) response_2 = self.client.post(reverse("polls:vote", args=(self.question.id,)), {"choice": self.choice2.id})
self.assertRedirects(response_2, reverse('polls:results', args=(self.question.id,))) self.assertRedirects(response_2, reverse('polls:results', args=(self.question.id,)))
self.assertFalse(Vote.objects.filter(user=self.user, question=self.question, choice=self.choice1).exists()) self.assertFalse(Vote.objects.filter(user=self.user, question=self.question, choice=self.choice1).exists())
self.assertTrue(Vote.objects.filter(user=self.user, question=self.question, choice=self.choice2).exists()) self.assertTrue(Vote.objects.filter(user=self.user, question=self.question, choice=self.choice2).exists())

View File

@ -9,8 +9,8 @@ urlpatterns = [
path("<int:pk>/results/", views.ResultsView.as_view(), name="results"), path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
path("<int:question_id>/vote/", views.vote, name="vote"), path("<int:question_id>/vote/", views.vote, name="vote"),
path("signup/", views.SignUpView.as_view(), name="signup"), path("signup/", views.SignUpView.as_view(), name="signup"),
path("upvote/<int:question_id>", views.up_down_vote, {'vote_type' : 'upvote'}, name="upvote"), path("upvote/<int:question_id>", views.up_down_vote, {'vote_type': 'upvote'}, name="upvote"),
path("downvote/<int:question_id>", views.up_down_vote, {'vote_type' : 'downvote'}, name="downvote"), path("downvote/<int:question_id>", views.up_down_vote, {'vote_type': 'downvote'}, name="downvote"),
path("search", views.search_poll, name="search_poll"), path("search", views.search_poll, name="search_poll"),
path("create", views.create_poll, name="create_poll") path("create", views.create_poll, name="create_poll")
] ]

View File

@ -2,7 +2,6 @@ import logging
from typing import Any from typing import Any
from django.shortcuts import get_object_or_404, render, redirect from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse
from django.views import generic from django.views import generic
from django.utils import timezone from django.utils import timezone
from django.urls import reverse_lazy, reverse from django.urls import reverse_lazy, reverse
@ -26,21 +25,21 @@ class IndexView(generic.ListView):
context_object_name = "latest_question_list" context_object_name = "latest_question_list"
def get_queryset(self): def get_queryset(self):
""" """
Return the last published questions that is published and haven't ended yet. Return the last published questions that is published and haven't ended yet.
""" """
now = timezone.now() now = timezone.now()
all_poll_queryset = Question.objects.filter( all_poll_queryset = Question.objects.filter(
Q(pub_date__lte=now) & ((Q(end_date__gte=now) | Q(end_date=None))) Q(pub_date__lte=now) & ((Q(end_date__gte=now) | Q(end_date=None)))
).order_by("-pub_date") ).order_by("-pub_date")
trend_poll_queryset = Question.objects.filter( trend_poll_queryset = Question.objects.filter(
Q(pub_date__lte=now) & ((Q(end_date__gte=now) | Q(end_date=None))) & Q(trend_score__gte=100) Q(pub_date__lte=now) & ((Q(end_date__gte=now) | Q(end_date=None))) & Q(trend_score__gte=100)
).order_by("trend_score", "end_date")[:3] ).order_by("trend_score")[:3]
queryset = {'all_poll' : all_poll_queryset, queryset = {'all_poll': all_poll_queryset,
'trend_poll' : trend_poll_queryset,} 'trend_poll': trend_poll_queryset, }
return queryset return queryset
class DetailView(LoginRequiredMixin, generic.DetailView): class DetailView(LoginRequiredMixin, generic.DetailView):
@ -102,7 +101,7 @@ class ResultsView(LoginRequiredMixin, generic.DetailView):
def get_context_data(self, **kwargs: Any) -> dict[str, Any]: def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
user_voted = None user_voted = None
question = self.get_object() question = self.get_object()
if question.sentimentvote_set.filter(user=self.request.user, question=question, vote_types=True).exists(): if question.sentimentvote_set.filter(user=self.request.user, question=question, vote_types=True).exists():
@ -113,6 +112,7 @@ class ResultsView(LoginRequiredMixin, generic.DetailView):
context['user_voted'] = user_voted context['user_voted'] = user_voted
return context return context
class SignUpView(generic.CreateView): class SignUpView(generic.CreateView):
""" """
View that responsible for Sign Up page. View that responsible for Sign Up page.
@ -153,7 +153,7 @@ def vote(request, question_id):
vote, created = Vote.objects.update_or_create( vote, created = Vote.objects.update_or_create(
user=request.user, user=request.user,
question=question, question=question,
defaults={'choice' : selected_choice} defaults={'choice': selected_choice}
) )
if created: if created:
@ -170,16 +170,15 @@ def vote(request, question_id):
else: else:
messages.error(request, "Invalid request method.") messages.error(request, "Invalid request method.")
return redirect("polls:index") return redirect("polls:index")
@login_required @login_required
def up_down_vote(request, question_id, vote_type): def up_down_vote(request, question_id, vote_type):
""" """
A function that control the upvote and downvote request. A function that control the upvote and downvote request.
""" """
ip = get_client_ip(request)
question = get_object_or_404(Question, pk=question_id) question = get_object_or_404(Question, pk=question_id)
if request.method == "POST": if request.method == "POST":
if vote_type == "upvote": if vote_type == "upvote":
if question.upvote(request.user): if question.upvote(request.user):
@ -187,7 +186,7 @@ def up_down_vote(request, question_id, vote_type):
elif vote_type == "downvote": elif vote_type == "downvote":
if question.downvote(request.user): if question.downvote(request.user):
messages.success(request, "You downvoted this Poll😭") messages.success(request, "You downvoted this Poll😭")
return redirect(reverse("polls:results", args=(question_id,))) return redirect(reverse("polls:results", args=(question_id,)))
@ -207,7 +206,7 @@ def get_client_ip(request):
def search_poll(request): def search_poll(request):
""" """
A function that handle the rendering of search result after user search with A function that handle the rendering of search result after user search with
search bar. search bar.
""" """
form = PollSearchForm form = PollSearchForm
@ -222,7 +221,7 @@ def search_poll(request):
# * If user search with empty string then show every poll. # * If user search with empty string then show every poll.
if q == '': if q == '':
results = Question.objects.all() results = Question.objects.all()
return render(request, 'polls/search.html', {'form':form, 'results':results, 'q':q}) return render(request, 'polls/search.html', {'form': form, 'results': results, 'q': q})
@login_required @login_required

View File

@ -17,7 +17,7 @@ def check_python_command():
return command return command
except FileNotFoundError: except FileNotFoundError:
continue continue
return None return None
def create_virtual_environment(env_name, python_command): def create_virtual_environment(env_name, python_command):
@ -31,7 +31,7 @@ def customize_virtual_environment():
def setup_environment_variables(python_command_in_venv): def setup_environment_variables(python_command_in_venv):
print("Setting up Django environment variables:") print("Setting up Django environment variables:")
# SECRET KEY # SECRET KEY
generate_secret_key = input("Generate a Django SECRET_KEY? (yes/no): ").strip().lower() generate_secret_key = input("Generate a Django SECRET_KEY? (yes/no): ").strip().lower()
if generate_secret_key == "yes": if generate_secret_key == "yes":
@ -39,7 +39,7 @@ def setup_environment_variables(python_command_in_venv):
'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())']).decode().strip() 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())']).decode().strip()
else: else:
secret_key = input("Enter Django SECRET_KEY: ").strip() secret_key = input("Enter Django SECRET_KEY: ").strip()
# DEBUG MODE # DEBUG MODE
while True: while True:
debug_mode = input("Enable DEBUG mode? (True/False): ").strip() debug_mode = input("Enable DEBUG mode? (True/False): ").strip()
@ -52,7 +52,7 @@ def setup_environment_variables(python_command_in_venv):
allowed_hosts = input("Enter ALLOWED_HOSTS (comma-separated, or press Enter for default): ").strip() allowed_hosts = input("Enter ALLOWED_HOSTS (comma-separated, or press Enter for default): ").strip()
if not allowed_hosts: if not allowed_hosts:
allowed_hosts = "*.ku.th,localhost,127.0.0.1,::1" allowed_hosts = "*.ku.th,localhost,127.0.0.1,::1"
# TZ # TZ
available_time_zones = ["Asia/Bangkok", "Japan", "UCT", "CST6CDT", "Custom"] available_time_zones = ["Asia/Bangkok", "Japan", "UCT", "CST6CDT", "Custom"]
@ -73,7 +73,7 @@ def setup_environment_variables(python_command_in_venv):
print("Invalid choice. Please enter a valid number.") print("Invalid choice. Please enter a valid number.")
except ValueError: except ValueError:
print("Invalid input. Please enter a valid number.") print("Invalid input. Please enter a valid number.")
email_host_password = input("Enter EMAIL_HOST_PASSWORD: ").strip() email_host_password = input("Enter EMAIL_HOST_PASSWORD: ").strip()
# SET # SET
@ -116,7 +116,7 @@ def main():
elif is_windows: elif is_windows:
activate_command = os.path.join(".venv", "Scripts", "activate") activate_command = os.path.join(".venv", "Scripts", "activate")
subprocess.run([activate_command], shell=True) subprocess.run([activate_command], shell=True)
python_command = os.path.join(".venv", "bin", "python") if is_posix else os.path.join(".venv", "Scripts", "python") python_command = os.path.join(".venv", "bin", "python") if is_posix else os.path.join(".venv", "Scripts", "python")
else: else:
print("Not setting up a virtual environment. Using the global Python interpreter.") print("Not setting up a virtual environment. Using the global Python interpreter.")
@ -154,19 +154,19 @@ def main():
print(f"==========================Install Requirement==========================") print(f"==========================Install Requirement==========================")
subprocess.run([python_command_in_venv, "-m", "pip", "install", "-r", "requirements.txt"]) subprocess.run([python_command_in_venv, "-m", "pip", "install", "-r", "requirements.txt"])
setup_environment_variables(python_command_in_venv) setup_environment_variables(python_command_in_venv)
subprocess.run([python_command_in_venv, "-m", "pip", "install", "-r", "requirements.txt"], check=True) subprocess.run([python_command_in_venv, "-m", "pip", "install", "-r", "requirements.txt"], check=True)
subprocess.run([python_command_in_venv, "manage.py", "migrate"], check=True) subprocess.run([python_command_in_venv, "manage.py", "migrate"], check=True)
subprocess.run([python_command_in_venv, "manage.py", "loaddata", "data/users.json"], check=True) subprocess.run([python_command_in_venv, "manage.py", "loaddata", "data/users.json"], check=True)
subprocess.run([python_command_in_venv, "manage.py", "loaddata", "data/polls.json"], check=True) subprocess.run([python_command_in_venv, "manage.py", "loaddata", "data/polls.json"], check=True)
start_server = input("Do you want to start the Django server? (yes/no): ").strip().lower() start_server = input("Do you want to start the Django server? (yes/no): ").strip().lower()
if start_server == "yes": if start_server == "yes":
print("=================================================") print("=================================================")
print("Django run in --insecure mode to load Static File") print("Django run in --insecure mode to load Static File")
print("==================================================") print("==================================================")
subprocess.run([python_command_in_venv, "manage.py", "runserver", "--insecure"], check=True) subprocess.run([python_command_in_venv, "manage.py", "runserver", "--insecure"], check=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f"Error: {e}") print(f"Error: {e}")
sys.exit(1) sys.exit(1)
@ -174,5 +174,6 @@ def main():
print("\nSetup process aborted.") print("\nSetup process aborted.")
sys.exit(1) sys.exit(1)
if __name__ == "__main__": if __name__ == "__main__":
main() main()