Added endpoint for querying avatars of users in a study group and for individual study group details

This commit is contained in:
Keannu Bernasol 2023-10-01 01:24:58 +08:00
parent 0ecfb2223a
commit c8fca412b8
7 changed files with 199 additions and 16 deletions

View file

@ -0,0 +1,21 @@
# Generated by Django 4.2.3 on 2023-09-30 15:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0002_initial'),
]
operations = [
migrations.AlterModelOptions(
name='customuser',
options={},
),
migrations.AlterUniqueTogether(
name='customuser',
unique_together={('first_name', 'last_name')},
),
]

View file

@ -135,7 +135,7 @@ paths:
name: id name: id
schema: schema:
type: integer type: integer
description: A unique integer value identifying this user. description: A unique integer value identifying this custom user.
required: true required: true
tags: tags:
- api - api
@ -155,7 +155,7 @@ paths:
name: id name: id
schema: schema:
type: integer type: integer
description: A unique integer value identifying this user. description: A unique integer value identifying this custom user.
required: true required: true
tags: tags:
- api - api
@ -187,7 +187,7 @@ paths:
name: id name: id
schema: schema:
type: integer type: integer
description: A unique integer value identifying this user. description: A unique integer value identifying this custom user.
required: true required: true
tags: tags:
- api - api
@ -218,7 +218,7 @@ paths:
name: id name: id
schema: schema:
type: integer type: integer
description: A unique integer value identifying this user. description: A unique integer value identifying this custom user.
required: true required: true
tags: tags:
- api - api
@ -763,6 +763,26 @@ paths:
items: items:
$ref: '#/components/schemas/StudyGroup' $ref: '#/components/schemas/StudyGroup'
description: '' description: ''
/api/v1/study_groups/{name}/:
get:
operationId: api_v1_study_groups_retrieve
parameters:
- in: path
name: name
schema:
type: string
required: true
tags:
- api
security:
- jwtAuth: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/StudyGroupDetail'
description: ''
/api/v1/study_groups/create/: /api/v1/study_groups/create/:
post: post:
operationId: api_v1_study_groups_create_create operationId: api_v1_study_groups_create_create
@ -851,7 +871,7 @@ paths:
schema: schema:
type: array type: array
items: items:
$ref: '#/components/schemas/StudyGroup' $ref: '#/components/schemas/StudyGroupDistance'
description: '' description: ''
/api/v1/subjects/: /api/v1/subjects/:
get: get:
@ -1068,21 +1088,18 @@ components:
readOnly: true readOnly: true
user: user:
type: string type: string
description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
only.
study_group: study_group:
type: string type: string
message_content: message_content:
type: string type: string
maxLength: 1024
timestamp: timestamp:
type: string type: string
format: date-time format: date-time
readOnly: true
required: required:
- id - id
- message_content - message_content
- study_group
- timestamp
- user
PasswordResetConfirm: PasswordResetConfirm:
type: object type: object
properties: properties:
@ -1348,6 +1365,75 @@ components:
- name - name
- subject - subject
- timestamp - timestamp
StudyGroupDetail:
type: object
properties:
id:
type: integer
readOnly: true
name:
type: string
students:
type: array
items:
type: string
subject:
type: string
location:
type: string
landmark:
type: string
nullable: true
timestamp:
type: string
format: date
readOnly: true
required:
- id
- location
- name
- students
- subject
- timestamp
StudyGroupDistance:
type: object
properties:
id:
type: integer
readOnly: true
name:
type: string
students:
type: array
items:
type: string
subject:
type: string
location:
type: string
landmark:
type: string
nullable: true
radius:
type: number
format: double
distance:
type: string
readOnly: true
default: 0
timestamp:
type: string
format: date
readOnly: true
required:
- distance
- id
- location
- name
- radius
- students
- subject
- timestamp
SubjectInstance: SubjectInstance:
type: object type: object
properties: properties:

View file

@ -4,6 +4,16 @@ from accounts.models import CustomUser
from subjects.models import Subject from subjects.models import Subject
from drf_extra_fields.geo_fields import PointField from drf_extra_fields.geo_fields import PointField
from landmarks.models import Landmark from landmarks.models import Landmark
from drf_extra_fields.fields import Base64ImageField
from djoser.serializers import UserSerializer as BaseUserSerializer
class CustomUserAvatarSerializer(BaseUserSerializer):
avatar = Base64ImageField()
class Meta(BaseUserSerializer.Meta):
model = CustomUser
fields = ['avatar', 'username']
class CustomUserKeyRelatedField(serializers.PrimaryKeyRelatedField): class CustomUserKeyRelatedField(serializers.PrimaryKeyRelatedField):
@ -13,6 +23,21 @@ class CustomUserKeyRelatedField(serializers.PrimaryKeyRelatedField):
return str(value) return str(value)
class StudyGroupDetailSerializer(serializers.ModelSerializer):
name = serializers.CharField()
students = serializers.StringRelatedField(many=True)
subject = serializers.SlugRelatedField(
many=False, slug_field='name', queryset=Subject.objects.all(), required=True, allow_null=False)
location = PointField()
landmark = serializers.SlugRelatedField(
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
class Meta:
model = StudyGroup
fields = '__all__'
read_only_fields = ['landmark', 'radius', 'students', 'distance']
class StudyGroupSerializer(serializers.ModelSerializer): class StudyGroupSerializer(serializers.ModelSerializer):
name = serializers.CharField() name = serializers.CharField()
students = serializers.StringRelatedField(many=True) students = serializers.StringRelatedField(many=True)

View file

@ -1,5 +1,5 @@
from django.urls import include, path from django.urls import include, path
from .views import StudyGroupListView, StudyGroupListNearView, StudyGroupCreateView from .views import StudyGroupListView, StudyGroupListNearView, StudyGroupCreateView, StudyGroupDetailView, StudyGroupAvatarsView
from rest_framework import routers from rest_framework import routers
router = routers.DefaultRouter() router = routers.DefaultRouter()
@ -7,7 +7,10 @@ router.register(r'create', StudyGroupCreateView,
basename='Create Study Group') basename='Create Study Group')
urlpatterns = [ urlpatterns = [
path('', StudyGroupListView.as_view()), path('', StudyGroupListView.as_view()),
path('near/', StudyGroupListNearView.as_view()),
path('', include(router.urls)), path('', include(router.urls)),
path('near/', StudyGroupListNearView.as_view()),
path('member_avatars/', StudyGroupAvatarsView.as_view()),
path('<str:name>/', StudyGroupDetailView.as_view()),
] ]

View file

@ -2,7 +2,7 @@ from django.shortcuts import render
from rest_framework import generics, mixins from rest_framework import generics, mixins
from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from .serializers import StudyGroupSerializer, StudyGroupCreateSerializer, StudyGroupDistanceSerializer from .serializers import StudyGroupSerializer, StudyGroupCreateSerializer, StudyGroupDistanceSerializer, StudyGroupDetailSerializer, CustomUserAvatarSerializer
from .models import StudyGroup from .models import StudyGroup
from subjects.models import Subject, SubjectInstance from subjects.models import Subject, SubjectInstance
from student_status.models import StudentStatus from student_status.models import StudentStatus
@ -12,10 +12,48 @@ from django.contrib.gis.db.models.functions import Distance
from rest_framework import status from rest_framework import status
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import permissions from rest_framework import permissions
from accounts.models import CustomUser
# Create your views here. # Create your views here.
class StudyGroupAvatarsView(generics.ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = CustomUserAvatarSerializer
queryset = CustomUser.objects.all()
def get_queryset(self):
# Get user
user = self.request.user
# Get status of user
user_status = StudentStatus.objects.filter(user=user).first()
# Return error if not in study group
if (not user_status.study_group):
raise exceptions.ValidationError("You are not in a study group")
# Get study group of user
user_study_group = user_status.study_group
# Get students in that study group
study_group_student_ids = user_study_group.students.values_list(
'user', flat=True)
# Then get user instances of those students
study_group_users = CustomUser.objects.filter(
id__in=study_group_student_ids)
# Return to be parsed by serializer
return study_group_users
class StudyGroupMembersAvatarView(generics.ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = StudyGroupCreateSerializer
queryset = CustomUser.objects.all()
class StudyGroupCreateView(viewsets.ModelViewSet): class StudyGroupCreateView(viewsets.ModelViewSet):
http_method_names = ['patch', 'post', 'delete'] http_method_names = ['patch', 'post', 'delete']
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
@ -23,6 +61,13 @@ class StudyGroupCreateView(viewsets.ModelViewSet):
queryset = StudyGroup.objects.all() queryset = StudyGroup.objects.all()
class StudyGroupDetailView(generics.RetrieveAPIView):
permission_classes = [IsAuthenticated]
serializer_class = StudyGroupDetailSerializer
queryset = StudyGroup.objects.all()
lookup_field = 'name'
class StudyGroupListView(generics.ListAPIView): class StudyGroupListView(generics.ListAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
serializer_class = StudyGroupSerializer serializer_class = StudyGroupSerializer

View file

@ -6,10 +6,13 @@ from study_groups.models import StudyGroup
class MessageSerializer(serializers.ModelSerializer): class MessageSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField( user = serializers.SlugRelatedField(
queryset=CustomUser.objects.all(), slug_field='full_name', required=True) queryset=CustomUser.objects.all(), slug_field='username', required=False)
study_group = serializers.SlugRelatedField( study_group = serializers.SlugRelatedField(
queryset=StudyGroup.objects.all(), slug_field='name', required=True) queryset=StudyGroup.objects.all(), slug_field='name', required=False)
message_content = serializers.CharField()
timestamp = serializers.DateTimeField(format="%I:%M %p", required=False)
class Meta: class Meta:
model = Message model = Message
fields = '__all__' fields = '__all__'
read_only_fields = ['user', 'study_group', 'timestamp']

View file

@ -48,5 +48,5 @@ class MessageViewSet(viewsets.ModelViewSet):
# Now fetch the Messages matching the study group id # Now fetch the Messages matching the study group id
messages = Message.objects.filter( messages = Message.objects.filter(
study_group=user_study_group).order_by('-timestamp') study_group=user_study_group).order_by('timestamp')
return messages return messages