mirror of
https://github.com/lemeow125/StudE-Backend.git
synced 2024-11-17 06:19:24 +08:00
Offloaded study group radius calculation to backend and fixed study groups serializer
This commit is contained in:
parent
018475b92c
commit
50fdebf222
2 changed files with 39 additions and 18 deletions
|
@ -14,6 +14,7 @@ class CustomUserKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
||||||
|
|
||||||
|
|
||||||
class StudyGroupSerializer(serializers.ModelSerializer):
|
class StudyGroupSerializer(serializers.ModelSerializer):
|
||||||
|
name = serializers.CharField()
|
||||||
users = CustomUserKeyRelatedField(
|
users = CustomUserKeyRelatedField(
|
||||||
queryset=CustomUser.objects.all(), many=True)
|
queryset=CustomUser.objects.all(), many=True)
|
||||||
subject = serializers.SlugRelatedField(
|
subject = serializers.SlugRelatedField(
|
||||||
|
@ -21,6 +22,7 @@ class StudyGroupSerializer(serializers.ModelSerializer):
|
||||||
location = PointField()
|
location = PointField()
|
||||||
landmark = serializers.SlugRelatedField(
|
landmark = serializers.SlugRelatedField(
|
||||||
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
|
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
|
||||||
|
radius = serializers.FloatField()
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
user = self.context['request'].user
|
user = self.context['request'].user
|
||||||
|
@ -40,7 +42,7 @@ class StudyGroupSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StudyGroup
|
model = StudyGroup
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = ['landmark']
|
read_only_fields = ['landmark', 'radius']
|
||||||
|
|
||||||
|
|
||||||
class StudyGroupMembershipSerializer(serializers.ModelSerializer):
|
class StudyGroupMembershipSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -4,11 +4,12 @@ from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from .serializers import StudyGroupSerializer
|
from .serializers import StudyGroupSerializer
|
||||||
from .models import StudyGroup
|
from .models import StudyGroup
|
||||||
from subjects.models import Subject
|
from subjects.models import Subject, SubjectInstance
|
||||||
from student_status.models import StudentStatus
|
from student_status.models import StudentStatus
|
||||||
from rest_framework import generics, viewsets, exceptions
|
from rest_framework import generics, viewsets, exceptions
|
||||||
from django.contrib.gis.geos import fromstr
|
from django.contrib.gis.geos import fromstr
|
||||||
from django.contrib.gis.db.models.functions import Distance
|
from django.contrib.gis.db.models.functions import Distance
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +21,11 @@ class StudyGroupListView(generics.ListAPIView):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
|
|
||||||
|
if not user.is_student:
|
||||||
|
raise PermissionDenied(
|
||||||
|
"You must be a student to view study groups"
|
||||||
|
)
|
||||||
|
|
||||||
if not user.is_student:
|
if not user.is_student:
|
||||||
raise PermissionDenied(
|
raise PermissionDenied(
|
||||||
"You must be a student to view study groups"
|
"You must be a student to view study groups"
|
||||||
|
@ -29,15 +35,14 @@ class StudyGroupListView(generics.ListAPIView):
|
||||||
user_course = user.course
|
user_course = user.course
|
||||||
print(user_course)
|
print(user_course)
|
||||||
|
|
||||||
# Get subject names related to the user's course
|
# Get the subject name of the student's subjects from SubjectInstance
|
||||||
subject_names = Subject.objects.filter(
|
user_subject_names = user.subjects.values_list('subject', flat=True)
|
||||||
course=user_course
|
print('user subjects:', user_subject_names)
|
||||||
).values_list('subject', flat=True)
|
# Get the corresponding Subject models
|
||||||
|
user_subjects = Subject.objects.filter(name__in=user_subject_names)
|
||||||
|
# Now fetch the StudyGroups with the matching Subject models
|
||||||
|
studygroups = StudyGroup.objects.filter(subject__in=user_subjects)
|
||||||
|
|
||||||
print(subject_names)
|
|
||||||
|
|
||||||
# Now fetch the StudyGroups with the matching subject names
|
|
||||||
studygroups = StudyGroup.objects.filter(subject_name__in=subject_names)
|
|
||||||
return studygroups
|
return studygroups
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,16 +69,30 @@ class StudyGroupListNearView(generics.ListAPIView):
|
||||||
user_course = user.course
|
user_course = user.course
|
||||||
print(user_course)
|
print(user_course)
|
||||||
|
|
||||||
# Get subject names related to the user's course
|
# Get the subject name of the student's subjects from SubjectInstance
|
||||||
subject_names = Subject.objects.filter(
|
user_subject_names = user.subjects.values_list('subject', flat=True)
|
||||||
course=user_course
|
# Get the corresponding Subject models
|
||||||
).values_list('subject', flat=True)
|
user_subjects = Subject.objects.filter(name__in=user_subject_names)
|
||||||
|
|
||||||
print(subject_names)
|
# Now fetch the StudyGroups with the matching Subject models that are within 100m
|
||||||
|
studygroups = StudyGroup.objects.filter(subject__in=user_subjects).annotate(
|
||||||
|
distance=Distance('location', user_location)).filter(distance__lte=100)
|
||||||
|
|
||||||
|
for group in studygroups:
|
||||||
|
# Get all StudentStatus locations of the group
|
||||||
|
group_locations = group.users.values_list('location', flat=True)
|
||||||
|
# Convert string locations to GEOSGeometry objects
|
||||||
|
point_locations = [fromstr(loc, srid=4326)
|
||||||
|
for loc in group_locations]
|
||||||
|
# Calculate distances between every pair of locations
|
||||||
|
distances = [(loc1.distance(
|
||||||
|
loc2)*100000)for loc1 in point_locations for loc2 in point_locations]
|
||||||
|
# Get the maximum distance
|
||||||
|
group_radius = max(distances) if distances else 0
|
||||||
|
group_radius = max(group_radius, 15)
|
||||||
|
# Annotate the group with the radius
|
||||||
|
group.radius = group_radius
|
||||||
|
|
||||||
# Now fetch the StudyGroups with the matching subject names that are within 50m
|
|
||||||
studygroups = StudyGroup.objects.filter(subject_name__in=subject_names).annotate(
|
|
||||||
distance=Distance('location', user_location)).filter(distance__lte=50)
|
|
||||||
return studygroups
|
return studygroups
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue