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

@ -7,3 +7,4 @@ class PollsConfig(AppConfig):
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()

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,7 +13,8 @@ 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)
@ -22,6 +24,7 @@ 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)
@ -31,6 +34,7 @@ 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(

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):

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

@ -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,7 +32,7 @@ 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)

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):
@ -21,7 +22,7 @@ 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())
@ -33,7 +34,7 @@ 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,)))
@ -42,7 +43,7 @@ class VoteViewTest(TestCase):
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/")
@ -55,8 +56,7 @@ 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'))

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):
@ -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:
@ -177,7 +177,6 @@ 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":
@ -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

@ -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()