- Django 4.2 + DRF + JWT + GraphQL - React 18 + MobX + styled-components - PostgreSQL 数据库 - Docker + Docker Compose + Nginx - 完整的功能模块(用户、版块、文章、服务、交互、版主管理) - 完整的文档(需求、部署、测试)
153 lines
5.6 KiB
Python
153 lines
5.6 KiB
Python
from rest_framework import viewsets, permissions, status
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
from django.db.models import Count, Q
|
|
from .models import User
|
|
from .serializers import (
|
|
UserSerializer,
|
|
UserDetailSerializer,
|
|
UserUpdateSerializer,
|
|
UserStatsSerializer
|
|
)
|
|
|
|
|
|
class UserViewSet(viewsets.ModelViewSet):
|
|
"""ViewSet for User model."""
|
|
|
|
queryset = User.objects.all()
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == 'retrieve' and self.kwargs.get('pk') == 'me':
|
|
return UserDetailSerializer
|
|
elif self.action in ['update', 'partial_update'] and self.kwargs.get('pk') == 'me':
|
|
return UserUpdateSerializer
|
|
return UserSerializer
|
|
|
|
def get_queryset(self):
|
|
# Only admins can see all users
|
|
if self.request.user.is_admin():
|
|
return User.objects.all()
|
|
# Regular users can only see themselves
|
|
return User.objects.filter(id=self.request.user.id)
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
"""Only admins can list all users."""
|
|
if not request.user.is_admin():
|
|
return Response(
|
|
{'detail': 'You do not have permission to perform this action.'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
return super().list(request, *args, **kwargs)
|
|
|
|
def retrieve(self, request, *args, **kwargs):
|
|
"""Get user details (me for current user)."""
|
|
if kwargs.get('pk') == 'me':
|
|
self.kwargs['pk'] = request.user.id
|
|
return super().retrieve(request, *args, **kwargs)
|
|
|
|
def update(self, request, *args, **kwargs):
|
|
"""Update user details (only me for regular users)."""
|
|
if kwargs.get('pk') == 'me':
|
|
self.kwargs['pk'] = request.user.id
|
|
elif not request.user.is_admin() and str(kwargs.get('pk')) != str(request.user.id):
|
|
return Response(
|
|
{'detail': 'You can only update your own profile.'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
return super().update(request, *args, **kwargs)
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def me(self, request):
|
|
"""Get current user details."""
|
|
serializer = self.get_serializer(request.user)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def stats(self, request, pk=None):
|
|
"""Get user statistics."""
|
|
if pk == 'me':
|
|
pk = request.user.id
|
|
user = self.get_object()
|
|
|
|
if str(user.id) != str(request.user.id) and not request.user.is_admin():
|
|
return Response(
|
|
{'detail': 'You do not have permission to view this user\'s stats.'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
|
|
from apps.articles.models import Article
|
|
from apps.featured_services.models import FeaturedService
|
|
from apps.interactions.models import Comment, Like, Favorite, Rating
|
|
|
|
return Response({
|
|
'articles_count': Article.objects.filter(author=user).count(),
|
|
'services_count': FeaturedService.objects.filter(submitter=user).count(),
|
|
'comments_count': Comment.objects.filter(author=user).count(),
|
|
'likes_count': Like.objects.filter(user=user).count(),
|
|
'favorites_count': Favorite.objects.filter(user=user).count(),
|
|
'ratings_count': Rating.objects.filter(user=user).count(),
|
|
})
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def favorites(self, request, pk=None):
|
|
"""Get user's favorites."""
|
|
if pk == 'me':
|
|
pk = request.user.id
|
|
user = self.get_object()
|
|
|
|
if str(user.id) != str(request.user.id):
|
|
return Response(
|
|
{'detail': 'You can only view your own favorites.'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
|
|
from apps.interactions.serializers import FavoriteSerializer
|
|
favorites = Favorite.objects.filter(user=user).select_related()
|
|
serializer = FavoriteSerializer(favorites, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def ratings(self, request, pk=None):
|
|
"""Get user's ratings."""
|
|
if pk == 'me':
|
|
pk = request.user.id
|
|
user = self.get_object()
|
|
|
|
if str(user.id) != str(request.user.id):
|
|
return Response(
|
|
{'detail': 'You can only view your own ratings.'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
|
|
from apps.interactions.serializers import RatingSerializer
|
|
ratings = Rating.objects.filter(user=user).select_related()
|
|
serializer = RatingSerializer(ratings, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def search(self, request):
|
|
"""Search users (admin only)."""
|
|
if not request.user.is_admin():
|
|
return Response(
|
|
{'detail': 'Only admins can search users.'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
|
|
query = request.query_params.get('q', '')
|
|
if query:
|
|
users = User.objects.filter(
|
|
Q(username__icontains=query) |
|
|
Q(email__icontains=query) |
|
|
Q(first_name__icontains=query)
|
|
)
|
|
else:
|
|
users = User.objects.all()
|
|
|
|
page = self.paginate_queryset(users)
|
|
if page is not None:
|
|
serializer = self.get_serializer(page, many=True)
|
|
return self.get_paginated_response(serializer.data)
|
|
|
|
serializer = self.get_serializer(users, many=True)
|
|
return Response(serializer.data) |