From 5e6bc64217b2c93ef25193f0b38583c5b79882f5 Mon Sep 17 00:00:00 2001 From: Mikhail Khromov Date: Tue, 20 Jun 2023 23:46:58 +0300 Subject: [PATCH 1/3] Views for projects are now models, not an integer --- .../0017_remove_project_views_count.py | 17 +++++++++++++++++ projects/models.py | 6 ------ projects/serializers.py | 7 +++++++ projects/views.py | 6 +++++- 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 projects/migrations/0017_remove_project_views_count.py diff --git a/projects/migrations/0017_remove_project_views_count.py b/projects/migrations/0017_remove_project_views_count.py new file mode 100644 index 00000000..33e52cc0 --- /dev/null +++ b/projects/migrations/0017_remove_project_views_count.py @@ -0,0 +1,17 @@ +# Generated by Django 4.1.3 on 2023-06-20 20:46 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("projects", "0016_alter_projectnews_files"), + ] + + operations = [ + migrations.RemoveField( + model_name="project", + name="views_count", + ), + ] diff --git a/projects/models.py b/projects/models.py index c32ad85b..a3d05bea 100644 --- a/projects/models.py +++ b/projects/models.py @@ -66,12 +66,6 @@ class Project(models.Model): objects = ProjectManager() - views_count = models.PositiveIntegerField(default=0) - - def increment_views_count(self): - self.views_count += 1 - self.save() - def get_short_description(self) -> Optional[str]: return self.description[:90] if self.description else None diff --git a/projects/serializers.py b/projects/serializers.py index 497c2bdf..f9fab99b 100644 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -2,6 +2,7 @@ from rest_framework import serializers from core.fields import CustomListField +from core.models import View from core.services import get_views_count, get_likes_count, is_fan from industries.models import Industry from projects.models import Project, Achievement, Collaborator, ProjectNews @@ -71,6 +72,7 @@ class ProjectDetailSerializer(serializers.ModelSerializer): short_description = serializers.SerializerMethodField() industry_id = serializers.IntegerField(required=False) likes_count = serializers.SerializerMethodField(method_name="count_likes") + views_count = serializers.SerializerMethodField(method_name="count_views") links = serializers.SerializerMethodField() @classmethod @@ -88,6 +90,11 @@ def get_short_description(cls, project): def count_likes(self, project): return LikesOnProject.objects.filter(project=project, is_liked=True).count() + def count_views(self, project): + # FIXME + # TODO: add caching here at least every 5 minutes, otherwise will be heavy load + return View.objects.filter(content_type=Project, content_object=project).count() + def update(self, instance, validated_data): instance = super().update(instance, validated_data) instance.save() diff --git a/projects/views.py b/projects/views.py index 352e409f..d908b640 100644 --- a/projects/views.py +++ b/projects/views.py @@ -6,6 +6,7 @@ from rest_framework.response import Response from rest_framework.views import APIView +from core.models import View from core.permissions import IsStaffOrReadOnly from core.serializers import SetLikedSerializer from core.services import add_view, set_like @@ -92,7 +93,10 @@ class ProjectDetail(generics.RetrieveUpdateDestroyAPIView): def retrieve(self, request, *args, **kwargs): instance = self.get_object() - instance.increment_views_count() + # create (or not, if it exists) a view object for project + View.objects.get_or_create( + user=request.user, content_type=Project, content_object=instance + ) serializer = self.get_serializer(instance) return Response(serializer.data) From 74a2cb6f1ff8e6e523b9b391e483ba4e0307e72a Mon Sep 17 00:00:00 2001 From: Mikhail Khromov Date: Tue, 20 Jun 2023 23:50:04 +0300 Subject: [PATCH 2/3] Views for projects are now models, not an integer --- projects/serializers.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/projects/serializers.py b/projects/serializers.py index f9fab99b..16ed7329 100644 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -139,6 +139,12 @@ class ProjectListSerializer(serializers.ModelSerializer): method_name="get_collaborator_count" ) vacancies = ProjectVacancyListSerializer(many=True, read_only=True) + views_count = serializers.SerializerMethodField(method_name="count_views") + + def count_views(self, project): + # FIXME + # TODO: add caching here at least every 5 minutes, otherwise will be heavy load + return View.objects.filter(content_type=Project, content_object=project).count() short_description = serializers.SerializerMethodField() @@ -179,9 +185,7 @@ class Meta: "views_count", ] - read_only_fields = [ - "leader", - ] + read_only_fields = ["leader", "views_count"] def is_valid(self, *, raise_exception=False): return super().is_valid(raise_exception=raise_exception) From 41754f67ed62b4ad9741dec00dd27227297a7c1b Mon Sep 17 00:00:00 2001 From: Mikhail Khromov Date: Wed, 21 Jun 2023 00:03:03 +0300 Subject: [PATCH 3/3] fix tests --- projects/serializers.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/projects/serializers.py b/projects/serializers.py index 16ed7329..1a0594ff 100644 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -1,4 +1,5 @@ from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType from rest_framework import serializers from core.fields import CustomListField @@ -93,7 +94,9 @@ def count_likes(self, project): def count_views(self, project): # FIXME # TODO: add caching here at least every 5 minutes, otherwise will be heavy load - return View.objects.filter(content_type=Project, content_object=project).count() + return View.objects.filter( + content_type=ContentType.objects.get_for_model(Project), object_id=project.pk + ).count() def update(self, instance, validated_data): instance = super().update(instance, validated_data) @@ -144,7 +147,9 @@ class ProjectListSerializer(serializers.ModelSerializer): def count_views(self, project): # FIXME # TODO: add caching here at least every 5 minutes, otherwise will be heavy load - return View.objects.filter(content_type=Project, content_object=project).count() + return View.objects.filter( + content_type=ContentType.objects.get_for_model(Project), object_id=project.pk + ).count() short_description = serializers.SerializerMethodField()