diff --git a/stude/student_status/migrations/0003_alter_studentstatus_subject.py b/stude/student_status/migrations/0003_alter_studentstatus_subject.py new file mode 100644 index 0000000..bfd4067 --- /dev/null +++ b/stude/student_status/migrations/0003_alter_studentstatus_subject.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.3 on 2023-09-05 12:19 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('subjects', '0002_alter_subject_name_alter_subjectinstance_subject'), + ('student_status', '0002_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='studentstatus', + name='subject', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='subjects.subject', to_field='name'), + ), + ] diff --git a/stude/student_status/models.py b/stude/student_status/models.py index bd4e1e7..a6cea2c 100644 --- a/stude/student_status/models.py +++ b/stude/student_status/models.py @@ -11,7 +11,7 @@ class StudentStatus(models.Model): CustomUser, on_delete=models.CASCADE, primary_key=True) location = gis_models.PointField(blank=True, null=True, srid=4326) subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.SET_NULL, null=True) + 'subjects.Subject', on_delete=models.SET_NULL, null=True, to_field='name') active = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now_add=True) landmark = models.ForeignKey( diff --git a/stude/student_status/views.py b/stude/student_status/views.py index a630a27..fb9d79e 100644 --- a/stude/student_status/views.py +++ b/stude/student_status/views.py @@ -7,6 +7,7 @@ from django.contrib.gis.db.models.functions import Distance from django.contrib.gis.geos import fromstr from .models import StudentStatus from .serializers import StudentStatusLocationSerializer, StudentStatusSerializer +from subjects.models import Subject, SubjectInstance class StudentStatusAPIView(generics.RetrieveUpdateAPIView): @@ -26,7 +27,7 @@ class ActiveStudentStatusListAPIView(generics.ListAPIView): def get_queryset(self): user = self.request.user - return StudentStatus.objects.filter(active=True and user != user) + return StudentStatus.objects.exclude(user=user).filter(active=True) class StudentStatusListByStudentStatusLocation(generics.ListAPIView): @@ -44,7 +45,15 @@ class StudentStatusListByStudentStatusLocation(generics.ListAPIView): if user_status.active is False: raise exceptions.ValidationError("Student Status is not active") - return StudentStatus.objects.filter(active=True and user != user).filter(subject__in=user.subjects.all()).annotate(distance=Distance('location', user_location)).filter(distance__lte=50) + # Get names of all subjects of the user + user_subject_names = user.subjects.values_list('subject', flat=True) + + # Exclude user + # Filter those only with the same subjects as the user + # Annotate the queryset with distance to the user + # Then filter so that only those within 50m remain + return StudentStatus.objects.exclude(user=user).filter(active=True).filter( + subject__name__in=user_subject_names).annotate(distance=Distance('location', user_location)).filter(distance__lte=50) class StudentStatusListByCurrentLocation(viewsets.ViewSet): @@ -60,8 +69,17 @@ class StudentStatusListByCurrentLocation(viewsets.ViewSet): if not location_str: raise exceptions.ValidationError("Location is required") + # Parse user location from the POST request user_location = fromstr(location_str, srid=4326) - queryset = StudentStatus.objects.filter(active=True and user != user).filter(subject__in=user.subjects.all()).annotate( + + # Get names of all subjects of the user + user_subject_names = user.subjects.values_list('subject', flat=True) + + # Exclude user + # Filter those only with the same subjects as the user + # Annotate the queryset with distance to the user + # Then filter so that only those within 50m remain + queryset = StudentStatus.objects.exclude(user=user).filter(active=True).filter(subject__name__in=user_subject_names).annotate( distance=Distance('location', user_location)).filter(distance__lte=50) serializer = StudentStatusLocationSerializer(queryset, many=True) return Response(serializer.data) diff --git a/stude/subjects/migrations/0002_alter_subject_name_alter_subjectinstance_subject.py b/stude/subjects/migrations/0002_alter_subject_name_alter_subjectinstance_subject.py new file mode 100644 index 0000000..626b9df --- /dev/null +++ b/stude/subjects/migrations/0002_alter_subject_name_alter_subjectinstance_subject.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.3 on 2023-09-05 12:19 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('subjects', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='subject', + name='name', + field=models.CharField(max_length=64, unique=True), + ), + migrations.AlterField( + model_name='subjectinstance', + name='subject', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'), + ), + ] diff --git a/stude/subjects/models.py b/stude/subjects/models.py index d10f6dc..18769f8 100644 --- a/stude/subjects/models.py +++ b/stude/subjects/models.py @@ -12,7 +12,7 @@ from semesters.models import Semester class Subject(models.Model): - name = models.CharField(max_length=64) + name = models.CharField(max_length=64, unique=True) students = models.ManyToManyField( CustomUser, blank=True) @@ -22,7 +22,7 @@ class Subject(models.Model): class SubjectInstance(models.Model): subject = models.ForeignKey( - Subject, on_delete=models.CASCADE) + Subject, on_delete=models.CASCADE, to_field='name') code = models.CharField(max_length=16) course = models.ForeignKey( Course, on_delete=models.CASCADE)