วันเสาร์ที่ 14 เมษายน พ.ศ. 2561

Commit 17 Wordbucket : fixed duplicated upload, role, like or dislike spam(change model)

Assignment1 : Wordbucket GitHub Link

Commit 17 Wordbucket : fixed duplicated upload, role, like or dislike spam(change model)

Commits on Apr 1, 2018

unit test

- แก้ unit test ก่อนปรับ model จากอันเดิม ซึ่งจะอธิบายการเปลี่ยนแปลงข้างล่างนี้

@@ -3,7 +3,7 @@
from django.http import HttpRequest
from django.template.loader import render_to_string
from wordbucket.views import home_page
-from wordbucket.models import Word, Explanation, Like_and_dislike
+from wordbucket.models import Word, Explanation, Like, Dislike
class HomePageTest(TestCase):
@@ -71,27 +71,29 @@ def test_saving_and_retrieving_like_and_dislike(self):
explanation_.word = word_
explanation_.save()
- first_votes_like = Like_and_dislike()
- first_votes_like.votes_like = 1
+ first_votes_like = Like()
+ first_votes_like.user_like = '1'
first_votes_like.explanation = explanation_
first_votes_like.save()
- second_votes_dislike = Like_and_dislike()
- second_votes_dislike.votes_dislike = 2
+ second_votes_dislike = Dislike()
+ second_votes_dislike.user_dislike = '2'
second_votes_dislike.explanation = explanation_
second_votes_dislike.save()
saved_explanation = Explanation.objects.first()
self.assertEqual(saved_explanation, explanation_)
- saved_likes_and_dislikes = Like_and_dislike.objects.all()
- self.assertEqual(saved_likes_and_dislikes.count(), 2)
+ saved_likes = Like.objects.all()
+ self.assertEqual(saved_likes.count(), 1)
+ saved_dislikes = Dislike.objects.all()
+ self.assertEqual(saved_dislikes.count(), 1)
- first_saved_votes_like = saved_likes_and_dislikes[0]
- second_saved_votes_like = saved_likes_and_dislikes[1]
- self.assertEqual(first_saved_votes_like.votes_like, 1)
+ first_saved_votes_like = saved_likes[0]
+ second_saved_votes_like = saved_dislikes[0]
+ self.assertEqual(first_saved_votes_like.user_like, '1')
self.assertEqual(first_saved_votes_like.explanation, explanation_)
- self.assertEqual(second_saved_votes_like.votes_dislike, 2)
+ self.assertEqual(second_saved_votes_like.user_dislike, '2')
self.assertEqual(second_saved_votes_like.explanation, explanation_)
class WordViewTest(TestCase):
@@ -192,13 +194,9 @@ def test_redirects_like_to_word_view(self):
explanation_ = Explanation()
explanation_.explanation_text = 'test'
+ explanation_.votes_like += 1
explanation_.word = word_
explanation_.save()
-
- votes_like = Like_and_dislike()
- votes_like.votes_like = 0
- votes_like.explanation = explanation_
- votes_like.save()
response = self.client.get(
'/%d/like' % (explanation_.id,)
@@ -210,16 +208,12 @@ def test_redirects_dislike_to_word_view(self):
explanation_ = Explanation()
explanation_.explanation_text = 'test'
+ explanation_.votes_dislike += 1
explanation_.word = word_
explanation_.save()
-
- votes_dislike = Like_and_dislike()
- votes_dislike.votes_dislike = 0
- votes_dislike.explanation = explanation_
- votes_dislike.save()
response = self.client.get(
- '/%d/like' % (explanation_.id,)
+ '/%d/dislike' % (explanation_.id,)
)
self.assertRedirects(response, '/%d/' % (explanation_.id,))


models.py

- ปรับ model ย้าย votes_like และ vote_dislike มาเก็บใน explanation (จากคำแนะนำของอาจารย์ เรื่องตอนแรกที่จะแยก like ของ user และ anonymous เลยทำ model ออกมาในลักษณะแรก) จึงได้ปรับมาเป็น anonymouse ไม่สามารถ like dislike ได้ user เท่านั้นที่ like dislike ได้ โดยตาราง Like เก็บ user ที่ like ใน entity user_like โดยตาราง Dislike ก็ทำคล้ายกันแค่เก็บ user ที่ dislike ไว้ใน entity user_dislike

@@ -15,16 +15,27 @@ class Explanation(models.Model):
#foreign key
word = models.ForeignKey(Word, on_delete=models.CASCADE)
explanation_text = models.CharField(max_length=600)
+ votes_like = models.IntegerField(default=0)
+ votes_dislike = models.IntegerField(default=0)
def __str__(self):
return self.explanation_text
+ def __int__(self):
+ return self.votes_like
+ def __int__(self):
+ return self.votes_dislike
-class Like_and_dislike(models.Model):
+class Like(models.Model):
#foreign key for Like and Dislike
explanation = models.ForeignKey(Explanation, on_delete=models.CASCADE)
- #votes count
- votes_like = models.IntegerField(default=0)
- votes_dislike = models.IntegerField(default=0)
+ #user votes count
+ user_like = models.TextField(default='')
def __str__(self):
- return self.votes_like
+ return self.user_like
+
+class Dislike(models.Model):
+ #foreign key for Like and Dislike
+ explanation = models.ForeignKey(Explanation, on_delete=models.CASCADE)
+ #user votes count
+ user_dislike = models.TextField(default='')
def __str__(self):
- return self.votes_dislike
+ return self.user_dislike


admin.py

- เนืองจากเปลี่ยนแปลง model จึงแก้ admin ด้วยเผื่อใช้

@@ -1,10 +1,11 @@
from django.contrib import admin
-from .models import Word, Explanation, Like_and_dislike
+from .models import Word, Explanation, Like, Dislike
# Register your models here.
admin.site.register(Word)
admin.site.register(Explanation)
-admin.site.register(Like_and_dislike)
+admin.site.register(Like)
+admin.site.register(Dislike)

templates/detail.html

- เนื่องจากการเปลี่ยนแปลง จึงเตือน user ที่ไม่ logged inไว้ข้างบน
- แก้ตัวแปรในลูปให้ถูกต้อง(votes_like และ votes_dislike ถูกเปลี่ยนมาเก็บในตาราง Explanation)
- แก้ให้ admin เท่านั้นที่ใช้ import export ได้


@@ -9,7 +9,8 @@ <h1>Word Bucket</h1>
<p><a href="{% url 'wordbucket:logout' %}">logout</a></p>
{% else %}
You are not logged in
- <a href="{% url 'wordbucket:login' %}">LOGIN</a>
+ <a href="{% url 'wordbucket:login' %}">LOGIN</a><br>
+ You can not like and dislike.
<br>
{% endif %}
@@ -25,25 +26,26 @@ <h2>{{ word }}</h2>
<table id="id_explanation_table">
{% for explanation in word.explanation_set.all %}
<tr>
- <td>explanation {{ forloop.counter }} : {{ explanation.explanation_text }}
- {% for vote in explanation.like_and_dislike_set.all %}<br>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <td>explanation {{ forloop.counter }} : {{ explanation.explanation_text }}<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- {{ vote.votes_like }} &nbsp;<a href="{% url 'wordbucket:like' explanation.id %}">LIKE</a>
- &nbsp; {{ vote.votes_dislike }} &nbsp;<a href="{% url 'wordbucket:dislike' explanation.id %}">DISLIKE</a>
- {% endfor %}<br><br>
+ {{ explanation.votes_like }} &nbsp;<a href="{% url 'wordbucket:like' explanation.id %}">LIKE</a>
+ &nbsp; {{ explanation.votes_dislike }} &nbsp;<a href="{% url 'wordbucket:dislike' explanation.id %}">DISLIKE</a>
+ <br><br>
</td>
</tr>
{% endfor %}
</table>
<br>
{% if user.is_authenticated %}
+ {% if user.get_username == 'admin' %}
<a href="{% url 'wordbucket:export' word.id %}">export</a><br><br>
<form action="{% url 'wordbucket:import' word.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="csv_file" />
<input type="submit" value="Upload" />
</form>
+ {% endif %}
{% endif %}
<a href="{% url 'wordbucket:home' %}">HOME</a>
</body>


views.py

- แก้ query/create ที่เกี่ยวกับ Like_and_dislike , votes_like , votes_dislike ทั้งหมด
- แก้ให้ไม่สามารถสร้าง word / explanation ที่เป็น "" (ช่องว่าง)ได้
- แก้ add_word และ add_explanation ให้ explanation ที่เหมือนกัน แต่คนละ word สามารถโพสได้
- แก้ vote_like และ vote_dislike ให้ปรับมาเป็น anonymouse ไม่สามารถ like dislike ได้ user เท่านั้นที่ like dislike ได้
- แก้ import csv ให้ไม่ข้ามไม่สร้าง explanation ที่ซ้ำกับที่มีอยู่แล้ว

@@ -2,7 +2,7 @@
from django.urls import reverse
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
-from wordbucket.models import Word, Explanation, Like_and_dislike
+from wordbucket.models import Word, Explanation, Like, Dislike
import string, csv, os, codecs
from django.http import HttpResponse
from io import TextIOWrapper
@@ -16,38 +16,44 @@ def home_page(request):
def view_word(request, word_id):
d_message = ""
word_ = Word.objects.get(id=word_id)
- return render(request, 'detail.html', {'word': word_, 'd_message': d_message})
+ like_ = Like.objects.all
+ dislike_ = Dislike.objects.all
+ return render(request, 'detail.html', {'word': word_, 'like': like_, 'dislike': dislike_, 'd_message': d_message})
def add_word(request):
d_message = ""
words = Word.objects.order_by('-date_pub')[:5]
word_reference = str(request.POST['word_input'])
+ explanation_reference = str(request.POST['explanation_input'])
# query for duplicate word
d_query = Word.objects.filter(word=word_reference)
- if not d_query :
+ if (not d_query) and (word_reference != '') :
word_ = Word.objects.create(word = request.POST['word_input'])
- explanation_ = Explanation.objects.create(explanation_text=request.POST['explanation_input'], word=word_)
- Like_and_dislike.objects.create(votes_like = 0, votes_dislike = 0, explanation = explanation_)
+ explanation_ = Explanation.objects.create(explanation_text=request.POST['explanation_input'], votes_like = 0, votes_dislike = 0, word=word_)
return redirect('/')
else :
- # duplacate word id
- dword_id = Word.objects.get(word = word_reference)
- explanation_ = Explanation.objects.create(explanation_text=request.POST['explanation_input'], word=dword_id)
- Like_and_dislike.objects.create(votes_like = 0, votes_dislike = 0, explanation = explanation_)
- d_message = "duplicate word, your explanation add to existing word."
- return render(request, 'home.html', {'words': words, 'd_message': d_message})
+ word_ = Word.objects.get(word=word_reference)
+ d_query2 = Explanation.objects.filter(explanation_text=explanation_reference, word=word_)
+ if (word_reference != '') and (not d_query2) :
+ # duplacate word id
+ dword_id = Word.objects.get(word = word_reference)
+ explanation_ = Explanation.objects.create(explanation_text=request.POST['explanation_input'], votes_like = 0, votes_dislike = 0, word=dword_id)
+ d_message = "duplicate word, your explanation add to existing word."
+ else :
+ d_message = "please enter the word"
+ alphabets = string.ascii_lowercase
+ return render(request, 'home.html', {'words': words, 'd_message': d_message, 'alphabets': alphabets})
def add_explanation(request, word_id):
word_ = Word.objects.get(id=word_id)
explanation_reference = str(request.POST['explanation_input'])
# query for duplicate explanation
- d_query = Explanation.objects.filter(explanation_text=explanation_reference)
- if not d_query :
- explanation_ = Explanation.objects.create(explanation_text=request.POST['explanation_input'], word=word_)
- Like_and_dislike.objects.create(votes_like = 0, votes_dislike = 0, explanation = explanation_)
+ d_query = Explanation.objects.filter(explanation_text=explanation_reference, word=word_)
+ if (not d_query) and (explanation_reference != '') :
+ explanation_ = Explanation.objects.create(explanation_text=request.POST['explanation_input'], votes_like = 0, votes_dislike = 0, word=word_)
return redirect('/%d/' % (word_.id,))
else :
- d_message = "duplicate explanation, please enter new explanation."
+ d_message = "duplicate or null explanation, please enter new explanation."
return render(request, 'detail.html', {'word': word_, 'd_message': d_message})
def search(request, word_search):
@@ -71,29 +77,28 @@ def search(request, word_search):
return render(request, 'search.html', {'word_found': word_found})
def vote_like(request, explanation_id):
- explanation_ = Explanation.objects.get(id=explanation_id)
- selected_explanation = explanation_.like_and_dislike_set.all()
- vote_like_ = selected_explanation.count()
- if vote_like_ == 0 :
- Like_and_dislike.objects.create(vote_like=1, explanation=explanation_)
- else :
- for voteslike in selected_explanation :
- voteslike.votes_like += 1
- voteslike.save()
- return HttpResponseRedirect(reverse('wordbucket:detail', args=(explanation_.word.id,)))
-
+ explanation_ = Explanation.objects.get(id=explanation_id)
+ if request.user.is_authenticated:
+ d_query = Like.objects.filter(user_like=request.user.username, explanation=explanation_)
+ if not d_query :
+ Like.objects.create(user_like=request.user.username, explanation=explanation_)
+ selected_explanation = explanation_.like_set.all()
+ vote_like_ = selected_explanation.count()
+ explanation_.votes_like = vote_like_
+ explanation_.save()
+ return HttpResponseRedirect(reverse('wordbucket:detail', args=(explanation_.word.id,)))
def vote_dislike(request, explanation_id):
- explanation_ = Explanation.objects.get(id=explanation_id)
- selected_explanation = explanation_.like_and_dislike_set.all()
- vote_dislike_ = selected_explanation.count()
- if vote_dislike_ == 0 :
- Like_and_dislike.objects.create(vote_dislike=1, explanation=explanation_)
- else :
- for votesdislike in selected_explanation :
- votesdislike.votes_dislike += 1
- votesdislike.save()
- return HttpResponseRedirect(reverse('wordbucket:detail', args=(explanation_.word.id,)))
+ explanation_ = Explanation.objects.get(id=explanation_id)
+ if request.user.is_authenticated:
+ d_query = Dislike.objects.filter(user_dislike=request.user.username, explanation=explanation_)
+ if not d_query :
+ Dislike.objects.create(user_dislike=request.user.username, explanation=explanation_)
+ selected_explanation = explanation_.dislike_set.all()
+ vote_dislike_ = selected_explanation.count()
+ explanation_.votes_dislike = vote_dislike_
+ explanation_.save()
+ return HttpResponseRedirect(reverse('wordbucket:detail', args=(explanation_.word.id,)))
# auth. part
@@ -136,6 +141,8 @@ def import_csv(request, word_id):
reader = csv.reader(csvfile)
next(reader)
for row in reader:
- explanation_ = Explanation.objects.create(explanation_text=row[1], word=word_)
- Like_and_dislike.objects.create(votes_like = 0, votes_dislike = 0, explanation = explanation_)
+ #duplicate explanation
+ d_query = Explanation.objects.filter(explanation_text=row[1], word=word_)
+ if (not d_query) and (row[1] != '') :
+ explanation_ = Explanation.objects.create(explanation_text=row[1], votes_like = 0, votes_dislike = 0, word=word_)
return HttpResponseRedirect(reverse('wordbucket:detail', args=(word_id,)))



ไม่มีความคิดเห็น:

แสดงความคิดเห็น