From 3152346ec739c92c0b1a51f37c3d231066e964bc Mon Sep 17 00:00:00 2001 From: sm4640 Date: Thu, 21 Aug 2025 00:31:04 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20[#88]=2024=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EB=82=B4=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nocodetools/services.py | 28 ++++++++++++++++++++++++++++ nocodetools/views.py | 9 ++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/nocodetools/services.py b/nocodetools/services.py index b19203b..36df671 100644 --- a/nocodetools/services.py +++ b/nocodetools/services.py @@ -7,6 +7,11 @@ from portfolios.models import Portfolio from projects.serializers import ProjectNocodetoolSerializer from portfolios.serializers import PortfolioNocodetoolSerializer +from django.utils import timezone +from django.db.models import F + +from django_redis import get_redis_connection + NOCODETOOL_MODEL_MAP = { 'project': Project, 'portfolio': Portfolio, @@ -27,3 +32,26 @@ class NocodetoolObjectMapService: def mapping_model_serializer(related_type: str): return NOCODETOOL_SERIALIZER_MAP.get(related_type, None) + + +class NocodetoolHitService: + def hit_once(obj, request, ttl=60*60*24): + user_key = request.user.id if request.user.is_authenticated else request.session.session_key + + if not user_key: + request.session.save() + user_key = request.session.session_key() + + today = timezone.localdate().isoformat() + key = f"viewed:obj:{obj.id}:{today}" + + redis_conn = get_redis_connection("default") + + added = redis_conn.sadd(key, user_key) + if added: + if redis_conn.ttl(key) == -1: + redis_conn.expire(key, ttl) + + obj.__class__.objects.filter(id=obj.id).update(view_count=F("view_count") + 1) + return True + return False diff --git a/nocodetools/views.py b/nocodetools/views.py index 76251b2..9f38de4 100644 --- a/nocodetools/views.py +++ b/nocodetools/views.py @@ -7,8 +7,8 @@ from django.db import transaction from .models import Code, Page, Element from .serializers import CodeSerializer -from .permissions import IsOwnerOrMemberInCreateAndUpdateAndDelete -from .services import NocodetoolObjectMapService +from .permissions import IsOwnerOrMemberInCreateAndUpdateAndDelete, IsNotPublished +from .services import NocodetoolObjectMapService, NocodetoolHitService from users.models import User from portfolios.models import Portfolio @@ -18,13 +18,16 @@ from bson import ObjectId class NoCodeToolAPIView(APIView): - permission_classes = [IsAuthenticated, IsOwnerOrMemberInCreateAndUpdateAndDelete] + permission_classes = [IsAuthenticated, IsNotPublished, IsOwnerOrMemberInCreateAndUpdateAndDelete] + @transaction.atomic def get(self, request): related_type = request.query_params.get("type") related_id = request.query_params.get("id") code_id = None if obj := NocodetoolObjectMapService.mapping_model_instance(related_type, related_id): + if obj.is_published: + NocodetoolHitService.hit_once(obj, request) code_id = ObjectId(obj.code_id) if not code_id: