From e4e93a3428193b39c703e4897d406e34aa974078 Mon Sep 17 00:00:00 2001 From: Okhin Date: Tue, 7 May 2019 17:10:48 +0200 Subject: [PATCH 1/2] Remving the django-und system for a classic score like system --- apps/rp/api/serializers.py | 17 +-- apps/rp/migrations/0021_auto_20190507_1438.py | 28 ++++ apps/rp/models.py | 25 ++-- apps/rp/tests/test_udlistview.py | 129 ------------------ apps/rp/tests/test_votes_views.py | 9 +- apps/rp/views/articles.py | 3 +- apps/rp/views/votes.py | 26 ---- project/settings/apps.py | 1 - requirements.txt | 1 - 9 files changed, 55 insertions(+), 184 deletions(-) create mode 100644 apps/rp/migrations/0021_auto_20190507_1438.py delete mode 100644 apps/rp/tests/test_udlistview.py delete mode 100644 apps/rp/views/votes.py diff --git a/apps/rp/api/serializers.py b/apps/rp/api/serializers.py index f3aa0b8..501ac45 100644 --- a/apps/rp/api/serializers.py +++ b/apps/rp/api/serializers.py @@ -22,23 +22,14 @@ class ArticleSerializer(serializers.ModelSerializer): tags = TagListSerializer(help_text=""" List of short tags to describe the article (eg."Privacy, Copyright"). Must be a list of tags, coma separated (or an empty string). - """) - und_score_up = serializers.IntegerField( - required=False, - help_text="This is used to increase the vote count by this value") - und_score_down = serializers.IntegerField( - required=False, - help_text="This is used to decrease the vote count by this value") - und_score = serializers.IntegerField( - required=False, - help_text="This is the actual computed score for an Article") + """, default="") class Meta: model = Article - fields = ('id', 'url', 'title', 'tags', 'extracts', 'status', - 'und_score_up', 'und_score_down', 'und_score') + fields = ('id', 'url', 'title', 'tags', 'extracts', 'status', 'score') def create(self, validated_data): article = Article.add_new_url(**validated_data) - article.save() + if article is not None: + article.save() return article diff --git a/apps/rp/migrations/0021_auto_20190507_1438.py b/apps/rp/migrations/0021_auto_20190507_1438.py new file mode 100644 index 0000000..26bca66 --- /dev/null +++ b/apps/rp/migrations/0021_auto_20190507_1438.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.2 on 2019-05-07 14:38 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('rp', '0020_article_original_status'), + ] + + operations = [ + migrations.RemoveField( + model_name='article', + name='und_score_down', + ), + migrations.RemoveField( + model_name='article', + name='und_score_up', + ), + migrations.AddField( + model_name='article', + name='score', + field=models.IntegerField(default=0), + ), + ] diff --git a/apps/rp/models.py b/apps/rp/models.py index f6b1525..8d35bde 100644 --- a/apps/rp/models.py +++ b/apps/rp/models.py @@ -4,7 +4,6 @@ from django.core import files from taggit.managers import TaggableManager from newspaper import Article as ArticleParser, ArticleException -from django_und.models import VoteMixin from django_fsm import FSMField, transition, RETURN_VALUE from io import BytesIO @@ -38,7 +37,8 @@ EXTRACTS_HELP_TEXT = """Please select short and helpful extracts from the article content. You should aim at around 500 characters. Use bracket ellipsis […] to cut parts not required to understand the context.""" -class Article(VoteMixin): + +class Article(models.Model): #: Logical state (eg. article submitted, published, or rejected) # This is unprotected because superuser should be able to change # the status from the django admin interface @@ -94,6 +94,9 @@ class Article(VoteMixin): #: Comma separated list of short tags to describe the article (eg: "Privacy", "Copyright"). tags = TaggableManager(blank=True) + #: Score of the article, modifiedby upvote and downvote methods + score = models.IntegerField(default=0) + class Meta: verbose_name = _("Article") verbose_name_plural = _("Articles") @@ -147,14 +150,14 @@ class Article(VoteMixin): @transition(field=status, source='DRAFT', target='DRAFT') @transition(field=status, source='NEW', target=RETURN_VALUE('NEW', 'DRAFT'), permission="rp.can_vote") - def upvote(self, by=None): + def upvote(self): """ Upvote the article score for the given user and remove previous votes. If the score crosses the threshold ```ARTICLE_SCORE_THRESHOLD```, automatically moves the article from _NEW_ to _DRAFT_. """ - super(Article, self).upvote(by) - if self.und_score >= ARTICLE_SCORE_THRESHOLD: + self.score += 1 + if self.score >= ARTICLE_SCORE_THRESHOLD - 1: return 'DRAFT' else: return self.status @@ -169,7 +172,7 @@ class Article(VoteMixin): votes. Draft articles can be downvoted but will not be moved back in the _NEW_ queue. """ - super(Article, self).downvote(by) + self.score -= 1 @classmethod def add_new_url(by=None, **data): @@ -184,13 +187,15 @@ class Article(VoteMixin): (article, created) = Article.objects.get_or_create(url=url, defaults=data) - # Let's add the tags - if tags: - article.tags.add(','.join([t for t in tags if len(t) > 0])) # If the article was already there, we should upvote it if not created: - article.upvote(str(by)) + if article.status == "REJECTED": + return None + article.upvote() + # Let's add the tags + if tags: + article.tags.add(','.join([t for t in tags if len(t) > 0])) try: r = requests.get(url, timeout=0.5) article.original_status = r.status_code diff --git a/apps/rp/tests/test_udlistview.py b/apps/rp/tests/test_udlistview.py deleted file mode 100644 index b76ec0c..0000000 --- a/apps/rp/tests/test_udlistview.py +++ /dev/null @@ -1,129 +0,0 @@ -from django.test import TestCase -from django.urls import reverse - -from userprofile.factories import ProfileFactory -from rp.factories import ArticleFactory -from rp.models import Article - - -class ArticleListTestCase(TestCase): - def setUp(self): - self.article = ArticleFactory(status='NEW') - self.article2 = ArticleFactory(status='NEW') - - self.user = ProfileFactory().user - self.user2 = ProfileFactory().user - self.user3 = ProfileFactory().user - - def test_empty_upvoted(self): - self.client.force_login(self.user) - response = self.client.get(reverse("rp:article-list", kwargs={ - "filter_view": "flux" - })) - assert response.status_code == 200 - # Get the context - context = response.context - assert context["und_votes"]["upvoted"].count() == 0 - assert context["und_votes"]["downvoted"].count() == 0 - - def test_upvoted(self): - self.article.upvote(self.user.username) - - self.client.force_login(self.user) - response = self.client.get(reverse("rp:article-list", kwargs={ - "filter_view": "flux" - })) - - assert list( - response.context["und_votes"]["upvoted"]) == [self.article.id] - assert list( - response.context["und_votes"]["downvoted"]) == [] - - def test_downvoted(self): - self.article.downvote(self.user.username) - - self.client.force_login(self.user) - response = self.client.get(reverse("rp:article-list", kwargs={ - "filter_view": "flux" - })) - - assert list( - response.context["und_votes"]["upvoted"]) == [] - assert list( - response.context["und_votes"]["downvoted"]) == [self.article.id] - - def test_2users(self): - self.article.downvote(self.user.username) - self.article2.upvote(self.user.username) - - self.article.upvote(self.user2.username) - - self.client.force_login(self.user) - response = self.client.get(reverse("rp:article-list", kwargs={ - "filter_view": "flux" - })) - - assert list( - response.context["und_votes"]["upvoted"]) == [self.article2.id] - assert list( - response.context["und_votes"]["downvoted"]) == [self.article.id] - - self.client.force_login(self.user2) - response = self.client.get(reverse("rp:article-list", kwargs={ - "filter_view": "flux" - })) - - assert list( - response.context["und_votes"]["upvoted"]) == [self.article.id] - assert list( - response.context["und_votes"]["downvoted"]) == [] - - def _test_filter_view(self, filter_view): - """Return list of articles ids in filter_view""" - response = self.client.get(reverse("rp:article-list", kwargs={ - "filter_view": filter_view - })) - - return sorted( - response.context["object_list"].values_list('id', flat=True)) - - def test_filter_view(self): - self.article.upvote(self.user.username) - self.article.upvote(self.user2.username) - - self.client.force_login(self.user) - - assert self._test_filter_view("flux") == sorted( - [self.article.pk, self.article2.pk] - ) - assert self._test_filter_view("published") == [] - assert self._test_filter_view("draft") == [] - assert self._test_filter_view("rejected") == [] - - self.article.upvote(self.user3.username) - - assert self._test_filter_view("flux") == sorted( - [self.article.pk, self.article2.pk] - ) - - self.article.save() - - assert self._test_filter_view("published") == [] - assert self._test_filter_view("draft") == [self.article.id] - assert self._test_filter_view("rejected") == [] - - self.article2.reject() - self.article2.save() - - assert self._test_filter_view("published") == [] - assert self._test_filter_view("flux") == [] - assert self._test_filter_view("draft") == [self.article.id] - assert self._test_filter_view("rejected") == [self.article2.id] - - self.article.publish() - self.article.save() - - assert self._test_filter_view("published") == [self.article.id] - assert self._test_filter_view("flux") == [] - assert self._test_filter_view("draft") == [] - assert self._test_filter_view("rejected") == [self.article2.id] diff --git a/apps/rp/tests/test_votes_views.py b/apps/rp/tests/test_votes_views.py index a711ab5..dec14bb 100644 --- a/apps/rp/tests/test_votes_views.py +++ b/apps/rp/tests/test_votes_views.py @@ -39,12 +39,17 @@ class VoteViewTestCase(TestCase): response = self.client.post(url_upvote) self.assertEqual(response.status_code, 200) article_db = Article.objects.get(id=self.article.id) - assert article_db.und_score == 1 + assert article_db.score == 1 + + response = self.client.post(url_upvote) + self.assertEqual(response.status_code, 200) + article_db.refresh_from_db() + assert article_db.score == 2 response = self.client.post(url_downvote) self.assertEqual(response.status_code, 200) article_db = Article.objects.get(id=self.article.id) - assert article_db.und_score == -1 + assert article_db.score == 1 def test_publish(self): url_publish = reverse("api:article-publish", kwargs={ diff --git a/apps/rp/views/articles.py b/apps/rp/views/articles.py index efc0dd6..109bbe6 100644 --- a/apps/rp/views/articles.py +++ b/apps/rp/views/articles.py @@ -19,7 +19,6 @@ from taggit.models import Tag from rp.forms import TagMultipleChoiceField from rp.models import Article -from .votes import UDList class ArticleList(ListView): @@ -58,7 +57,7 @@ class ArticleList(ListView): return context -class ArticleListFlux(LoginRequiredMixin, UDList): +class ArticleListFlux(LoginRequiredMixin, ListView): model = Article paginate_by = 10 diff --git a/apps/rp/views/votes.py b/apps/rp/views/votes.py deleted file mode 100644 index 19e62ec..0000000 --- a/apps/rp/views/votes.py +++ /dev/null @@ -1,26 +0,0 @@ -from django.views.generic import ListView -from django.contrib.contenttypes.models import ContentType - - -class UDList(ListView): - """ - Adds id upvoted by user - """ - def get_context_data(self, **kwargs): - content_type = ContentType.objects.get_for_model(self.model) - queryset = self.get_queryset() - context = super().get_context_data(**kwargs) - - context["und_votes"] = { - "upvoted": queryset.filter( - und_votes__username=self.request.user.username, - und_votes__content_type=content_type, - und_votes__score__gt=0 - ).values_list("id", flat=True), - "downvoted": queryset.filter( - und_votes__username=self.request.user.username, - und_votes__content_type=content_type, - und_votes__score__lt=0 - ).values_list("id", flat=True) - } - return context diff --git a/project/settings/apps.py b/project/settings/apps.py index d76c201..1c06f64 100644 --- a/project/settings/apps.py +++ b/project/settings/apps.py @@ -19,7 +19,6 @@ CONTRIB_APPS = [ "rest_framework", # http://www.django-rest-framework.org/ "rest_framework.authtoken", - "django_und", # https://github.com/luxcem/django_und "taggit", "crispy_forms", "django_markdown2", diff --git a/requirements.txt b/requirements.txt index 6423d50..7d8509f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,6 @@ djangorestframework==3.6.3 django-extensions==1.7.9 django-imagekit==4.0 django-taggit==0.22.0 -django-und Pillow==4.1.0 selenium newspaper3k -- GitLab From b9a7300a05ed10cc6e0553b895c62c7d20bdcee6 Mon Sep 17 00:00:00 2001 From: Okhin Date: Tue, 7 May 2019 17:12:12 +0200 Subject: [PATCH 2/2] FIxing the import script --- apps/core/management/commands/import_old_rp.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/core/management/commands/import_old_rp.py b/apps/core/management/commands/import_old_rp.py index 5e74ef0..761d52f 100644 --- a/apps/core/management/commands/import_old_rp.py +++ b/apps/core/management/commands/import_old_rp.py @@ -73,10 +73,7 @@ class Command(BaseCommand): article.website = website.group(1) # Raise the score if needed - if item['note'] > 0: - article.und_score_up = item['note'] - if item['note'] < 0: - article.und_score_down = abs(item['note']) + article.score = item['note'] article.save() article.refresh_from_db() -- GitLab