✨ Feat: [#88] 24시간 내 조회수 중복 방지
This commit is contained in:
@@ -7,6 +7,11 @@ from portfolios.models import Portfolio
|
|||||||
from projects.serializers import ProjectNocodetoolSerializer
|
from projects.serializers import ProjectNocodetoolSerializer
|
||||||
from portfolios.serializers import PortfolioNocodetoolSerializer
|
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 = {
|
NOCODETOOL_MODEL_MAP = {
|
||||||
'project': Project,
|
'project': Project,
|
||||||
'portfolio': Portfolio,
|
'portfolio': Portfolio,
|
||||||
@@ -27,3 +32,26 @@ class NocodetoolObjectMapService:
|
|||||||
|
|
||||||
def mapping_model_serializer(related_type: str):
|
def mapping_model_serializer(related_type: str):
|
||||||
return NOCODETOOL_SERIALIZER_MAP.get(related_type, None)
|
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
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ from django.db import transaction
|
|||||||
|
|
||||||
from .models import Code, Page, Element
|
from .models import Code, Page, Element
|
||||||
from .serializers import CodeSerializer
|
from .serializers import CodeSerializer
|
||||||
from .permissions import IsOwnerOrMemberInCreateAndUpdateAndDelete
|
from .permissions import IsOwnerOrMemberInCreateAndUpdateAndDelete, IsNotPublished
|
||||||
from .services import NocodetoolObjectMapService
|
from .services import NocodetoolObjectMapService, NocodetoolHitService
|
||||||
|
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from portfolios.models import Portfolio
|
from portfolios.models import Portfolio
|
||||||
@@ -18,13 +18,16 @@ from bson import ObjectId
|
|||||||
|
|
||||||
|
|
||||||
class NoCodeToolAPIView(APIView):
|
class NoCodeToolAPIView(APIView):
|
||||||
permission_classes = [IsAuthenticated, IsOwnerOrMemberInCreateAndUpdateAndDelete]
|
permission_classes = [IsAuthenticated, IsNotPublished, IsOwnerOrMemberInCreateAndUpdateAndDelete]
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
related_type = request.query_params.get("type")
|
related_type = request.query_params.get("type")
|
||||||
related_id = request.query_params.get("id")
|
related_id = request.query_params.get("id")
|
||||||
code_id = None
|
code_id = None
|
||||||
if obj := NocodetoolObjectMapService.mapping_model_instance(related_type, related_id):
|
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)
|
code_id = ObjectId(obj.code_id)
|
||||||
|
|
||||||
if not code_id:
|
if not code_id:
|
||||||
|
|||||||
Reference in New Issue
Block a user