gukgjzkgjhgjh

This commit is contained in:
2026-04-20 00:04:15 +02:00
parent 5280a87e8b
commit 659999f4fd
409 changed files with 19957 additions and 5176 deletions

View File

@@ -1,3 +1,157 @@
from django.shortcuts import render
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework.permissions import IsAuthenticated
from social.hubs.models import Tags
from .models import Post, PostVote
from .permissions import CanDeletePost, IsPostAuthorOnly
from .serializers import PostSerializer, PostVoteSerializer, TagAttachSerializer
# ---------------------------------------------------------------------------
# Post ViewSet
# ---------------------------------------------------------------------------
@extend_schema_view(
list=extend_schema(
tags=["posts"],
summary="List posts",
description="Returns posts. Filter by `hub` query param to scope to a hub.",
),
retrieve=extend_schema(
tags=["posts"],
summary="Retrieve a post",
),
create=extend_schema(
tags=["posts"],
summary="Create a post",
description="Creates a post. The requesting user is set as the author automatically.",
),
update=extend_schema(
tags=["posts"],
summary="Replace a post",
description="Full update. Author only.",
),
partial_update=extend_schema(
tags=["posts"],
summary="Update a post",
description="Partial update. Author only.",
),
destroy=extend_schema(
tags=["posts"],
summary="Delete a post",
description="Soft-deletes the post. Author, superuser, hub owner, or hub moderator with `managing_posts`.",
),
)
class PostViewSet(viewsets.ModelViewSet):
serializer_class = PostSerializer
filterset_fields = ['hub', 'author', 'reply_to']
search_fields = ['content']
ordering_fields = ['created_at']
ordering = ['-created_at']
def get_permissions(self):
if self.action == 'destroy':
return [CanDeletePost()]
if self.action in ('update', 'partial_update'):
return [IsPostAuthorOnly()]
return [IsAuthenticated()]
def get_queryset(self):
qs = Post.objects.select_related('author', 'hub').prefetch_related('tags', 'contents')
hub_id = self.request.query_params.get('hub')
if hub_id:
qs = qs.filter(hub_id=hub_id)
return qs
def perform_create(self, serializer):
serializer.save(author=self.request.user)
# ------------------------------------------------------------------
# Tag attachment actions
# ------------------------------------------------------------------
@extend_schema(
tags=["posts"],
summary="Attach a tag to a post",
description=(
"Attaches an existing hub tag to the post. "
"The tag must belong to the same hub as the post. "
"Any authenticated hub member can attach tags."
),
request=TagAttachSerializer,
responses={200: PostSerializer},
)
@action(detail=True, methods=['post'], url_path='tags/attach')
def attach_tag(self, request, pk=None):
post = self.get_object()
ser = TagAttachSerializer(data=request.data)
ser.is_valid(raise_exception=True)
try:
tag = Tags.objects.get(pk=ser.validated_data['tag_id'], hub=post.hub)
except Tags.DoesNotExist:
raise ValidationError({'tag_id': 'Tag not found or does not belong to this post\'s hub.'})
post.tags.add(tag)
return Response(PostSerializer(post, context={'request': request}).data)
@extend_schema(
tags=["posts"],
summary="Detach a tag from a post",
description=(
"Removes a tag from the post. "
"Post author, hub owner, site admin, or moderator with `managing_posts` can detach."
),
request=TagAttachSerializer,
responses={200: PostSerializer},
)
@action(detail=True, methods=['post'], url_path='tags/detach')
def detach_tag(self, request, pk=None):
post = self.get_object()
ser = TagAttachSerializer(data=request.data)
ser.is_valid(raise_exception=True)
user = request.user
hub = post.hub
is_author = post.author == user
is_hub_owner = hub and hub.owner == user
is_moderator = hub and hub.moderators.filter(user=user, managing_posts=True).exists()
if not (is_author or user.is_superuser or is_hub_owner or is_moderator):
raise PermissionDenied('Only the post author, hub owner, admin, or moderator with managing_posts can detach tags.')
try:
tag = Tags.objects.get(pk=ser.validated_data['tag_id'], hub=post.hub)
except Tags.DoesNotExist:
raise ValidationError({'tag_id': 'Tag not found or does not belong to this post\'s hub.'})
post.tags.remove(tag)
return Response(PostSerializer(post, context={'request': request}).data)
# ------------------------------------------------------------------
# Vote action
# ------------------------------------------------------------------
@extend_schema(
tags=["posts"],
summary="Vote on a post",
description="Cast or update a vote (`1` = upvote, `-1` = downvote) on a post.",
request=PostVoteSerializer,
responses={200: PostVoteSerializer},
)
@action(detail=True, methods=['post'])
def vote(self, request, pk=None):
post = self.get_object()
ser = PostVoteSerializer(data={**request.data, 'post': post.pk, 'user': request.user.pk})
ser.is_valid(raise_exception=True)
vote_obj, _ = PostVote.objects.update_or_create(
post=post,
user=request.user,
defaults={'vote': ser.validated_data['vote']},
)
return Response(PostVoteSerializer(vote_obj).data)
# Create your views here.