Completed backend

This commit is contained in:
Stepan 2025-12-28 16:22:33 +01:00
parent ed84b97f58
commit 9a376b0961
6 changed files with 51 additions and 14 deletions

View File

@ -1,9 +1,9 @@
from django.contrib import admin from django.contrib import admin
from .models import Publication, Rating from .models import Publication, Rating, Category
# Register your models here. # Register your models here.
class PublicationAdmin(admin.ModelAdmin): class PublicationAdmin(admin.ModelAdmin):
list_display = ('pk', 'content_type', 'is_pinned', 'user', 'time_created', 'time_updated') list_display = ('pk', 'content_type', 'category', 'is_pinned', 'user', 'time_created', 'time_updated')
list_display_links = ('pk', 'content_type') list_display_links = ('pk', 'content_type')
list_filter = ('content_type', 'is_pinned') list_filter = ('content_type', 'is_pinned')
readonly_fields = ('time_created', 'time_updated') readonly_fields = ('time_created', 'time_updated')
@ -17,3 +17,4 @@ class RatingAdmin(admin.ModelAdmin):
admin.site.register(Publication, PublicationAdmin) admin.site.register(Publication, PublicationAdmin)
admin.site.register(Rating, RatingAdmin) admin.site.register(Rating, RatingAdmin)
admin.site.register(Category)

View File

@ -1,5 +1,6 @@
from typing import TypeVar from typing import TypeVar
from django.db.models import Avg from django.db.models import Avg
from django.db.models.functions import Coalesce
from django.db import models from django.db import models
T = TypeVar('T') T = TypeVar('T')
@ -7,7 +8,7 @@ T = TypeVar('T')
class PublicationQuerySet(models.QuerySet[T]): class PublicationQuerySet(models.QuerySet[T]):
def with_score(self): def with_score(self):
qs = self qs = self
qs = qs.annotate(average_score=Avg("ratings__score")) qs = qs.annotate(average_score=Coalesce(Avg("ratings__score"), 0.0))
return qs return qs
def only_publish(self): def only_publish(self):

View File

@ -48,10 +48,6 @@ class Publication(models.Model):
def __str__(self): def __str__(self):
return f'Content #{self.pk}' return f'Content #{self.pk}'
@property
def average_score(self) -> int:
return getattr(self, "average_score", None)
def clean(self): def clean(self):
errors = [] errors = []

View File

@ -12,7 +12,31 @@ class CategorySerializer(serializers.ModelSerializer):
class PublicationSerializer(serializers.ModelSerializer): class PublicationSerializer(serializers.ModelSerializer):
category_detail = CategorySerializer(source="category", read_only=True) category_detail = CategorySerializer(source="category", read_only=True)
user_detail = PublicUserSerializer(source="user", read_only=True) user_detail = PublicUserSerializer(source="user", read_only=True)
average_score = serializers.IntegerField(read_only=True) average_score = serializers.SerializerMethodField(read_only=True)
def get_average_score(self, obj):
return getattr(obj, 'average_score', 0)
def validate(self, attrs):
content_type = attrs.get('content_type')
image = attrs.get('image')
video = attrs.get('video')
errors = {}
if content_type == 'image' and not image:
errors['image'] = 'Required image file'
if content_type == 'video' and not video:
errors['video'] = 'Required video file'
if image and video:
errors['non_field_errors'] = 'You must upload either a video or an image, not both'
if errors:
raise serializers.ValidationError(errors)
return attrs
class Meta: class Meta:
model = Publication model = Publication

View File

@ -40,6 +40,9 @@ class PublicationsAPIView(ListCreateAPIView):
return super().get_permissions() return super().get_permissions()
def perform_create(self, serializer: PublicationSerializer):
serializer.save(user=self.request.user)
@extend_schema( @extend_schema(
tags=['Publications'], tags=['Publications'],
summary='Publication details', summary='Publication details',
@ -67,6 +70,9 @@ class AdminPublicationsAPIView(PublicationsAPIView):
def get_permissions(self): def get_permissions(self):
return [IsProfessorOnly()] return [IsProfessorOnly()]
def perform_create(self, serializer: AdminPublicationSerializer):
serializer.save(user=self.request.user)
@extend_schema( @extend_schema(
tags=['Publications'], tags=['Publications'],
summary='CRUD for publication (only admin or professor)', summary='CRUD for publication (only admin or professor)',
@ -92,10 +98,11 @@ class CategoryListAPIView(ListCreateAPIView):
filter_backends = [filters.SearchFilter, filters.OrderingFilter] filter_backends = [filters.SearchFilter, filters.OrderingFilter]
ordering = ['name'] ordering = ['name']
search_fields = ['name'] search_fields = ['name']
pagination_class = None
def get_permissions(self): def get_permissions(self):
if self.request.method == 'POST': if self.request.method == 'POST':
return [IsAdminUser] return [IsAdminUser()]
return super().get_permissions() return super().get_permissions()
@extend_schema( @extend_schema(

View File

@ -5,7 +5,7 @@ from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status from rest_framework import status
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView, ListAPIView, RetrieveAPIView from rest_framework.generics import RetrieveUpdateDestroyAPIView, ListAPIView, RetrieveAPIView, ListCreateAPIView
from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
@ -87,9 +87,17 @@ class UserAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = UserForAdminSerializer serializer_class = UserForAdminSerializer
permission_classes = [IsAdminUser] permission_classes = [IsAdminUser]
@extend_schema(tags=['Users'], @extend_schema(
summary='List of all available school ids (only admin)') tags=['Users'],
class SchoolListAPIView(ListAPIView): methods=['GET'],
summary='List school ids',
)
@extend_schema(
tags=['Users'],
methods=['POST'],
summary='Create new school id (only admin)',
)
class SchoolListAPIView(ListCreateAPIView):
queryset = SchoolID.objects.all() queryset = SchoolID.objects.all()
serializer_class = SchoolIDSerializer serializer_class = SchoolIDSerializer
permission_classes = [IsAdminUser] permission_classes = [IsAdminUser]