Compare commits

..

No commits in common. "2a11a30cd55c7b16d0c79e7e1a8e8e1458540d71" and "ed84b97f583f61ca88716d658eb695f1c3a2f726" have entirely different histories.

7 changed files with 14 additions and 54 deletions

View File

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

View File

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

View File

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

View File

@ -12,31 +12,7 @@ class CategorySerializer(serializers.ModelSerializer):
class PublicationSerializer(serializers.ModelSerializer):
category_detail = CategorySerializer(source="category", read_only=True)
user_detail = PublicUserSerializer(source="user", 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
average_score = serializers.IntegerField(read_only=True)
class Meta:
model = Publication

View File

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

View File

@ -12,14 +12,11 @@ django-rest-framework==0.1.0
djangorestframework==3.16.1
djangorestframework_simplejwt==5.5.1
drf-spectacular==0.29.0
gunicorn==23.0.0
idna==3.11
inflection==0.5.1
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
oauthlib==3.3.1
packaging==25.0
pillow==12.0.0
pycparser==2.23
PyJWT==2.10.1
python-dotenv==1.2.1

View File

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