mirror of
https://github.com/lemeow125/StudE-Backend.git
synced 2025-06-28 16:25:44 +08:00
Removed associative entity and fixed relationship between student status and study group
This commit is contained in:
parent
771300f933
commit
7dc80caee7
23 changed files with 266 additions and 253 deletions
|
@ -1,7 +1,6 @@
|
|||
from django.contrib import admin
|
||||
from .models import StudyGroup, StudyGroupMembership
|
||||
from .models import StudyGroup
|
||||
from leaflet.admin import LeafletGeoAdmin
|
||||
|
||||
|
||||
admin.site.register(StudyGroup, LeafletGeoAdmin)
|
||||
admin.site.register(StudyGroupMembership)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
||||
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||
|
||||
import django.contrib.gis.db.models.fields
|
||||
from django.db import migrations, models
|
||||
|
@ -10,8 +10,8 @@ class Migration(migrations.Migration):
|
|||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('student_status', '0001_initial'),
|
||||
('subjects', '0001_initial'),
|
||||
('landmarks', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
@ -23,20 +23,8 @@ class Migration(migrations.Migration):
|
|||
('location', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
|
||||
('active', models.BooleanField(default=False)),
|
||||
('timestamp', models.DateField(auto_now_add=True)),
|
||||
('landmark', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark')),
|
||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StudyGroupMembership',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('study_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='study_groups.studygroup')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='student_status.studentstatus')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='studygroup',
|
||||
name='users',
|
||||
field=models.ManyToManyField(through='study_groups.StudyGroupMembership', to='student_status.studentstatus'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# Generated by Django 4.2.3 on 2023-09-24 10:59
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('landmarks', '0001_initial'),
|
||||
('study_groups', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='studygroup',
|
||||
name='landmark',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark'),
|
||||
),
|
||||
]
|
|
@ -7,8 +7,6 @@ from django.contrib.gis.geos import Point
|
|||
|
||||
class StudyGroup(models.Model):
|
||||
name = models.CharField(max_length=48)
|
||||
users = models.ManyToManyField(
|
||||
'student_status.StudentStatus', through='StudyGroupMembership')
|
||||
location = gis_models.PointField(blank=True, null=True, srid=4326)
|
||||
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
|
||||
active = models.BooleanField(default=False)
|
||||
|
@ -18,13 +16,3 @@ class StudyGroup(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class StudyGroupMembership(models.Model):
|
||||
user = models.ForeignKey(
|
||||
'student_status.StudentStatus', on_delete=models.CASCADE)
|
||||
study_group = models.ForeignKey(
|
||||
'study_groups.StudyGroup', on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return f'StudyGroupMembership: User={self.user}, StudyGroup={self.study_group.name}'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from rest_framework import serializers
|
||||
from .models import StudyGroup, StudyGroupMembership
|
||||
from .models import StudyGroup
|
||||
from accounts.models import CustomUser
|
||||
from subjects.models import Subject
|
||||
from drf_extra_fields.geo_fields import PointField
|
||||
|
@ -15,8 +15,7 @@ class CustomUserKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
|||
|
||||
class StudyGroupSerializer(serializers.ModelSerializer):
|
||||
name = serializers.CharField()
|
||||
users = CustomUserKeyRelatedField(
|
||||
queryset=CustomUser.objects.all(), many=True)
|
||||
students = serializers.StringRelatedField(many=True)
|
||||
subject = serializers.SlugRelatedField(
|
||||
many=False, slug_field='name', queryset=Subject.objects.all(), required=True, allow_null=False)
|
||||
location = PointField()
|
||||
|
@ -42,14 +41,4 @@ class StudyGroupSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = StudyGroup
|
||||
fields = '__all__'
|
||||
read_only_fields = ['landmark', 'radius']
|
||||
|
||||
|
||||
class StudyGroupMembershipSerializer(serializers.ModelSerializer):
|
||||
user = serializers.CharField(source='accounts.CustomUser', read_only=True)
|
||||
subject = serializers.CharField(
|
||||
source='study_groups.StudyGroup', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = StudyGroupMembership
|
||||
fields = '__all__'
|
||||
read_only_fields = ['landmark', 'radius', 'students']
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from django.urls import include, path
|
||||
from .views import StudyGroupListView, StudyGroupListNearView, StudyGroupMembershipViewSet
|
||||
from .views import StudyGroupListView, StudyGroupListNearView
|
||||
|
||||
urlpatterns = [
|
||||
path('', StudyGroupListView.as_view()),
|
||||
path('near/', StudyGroupListNearView.as_view()),
|
||||
path('membership/', StudyGroupMembershipViewSet.as_view()),
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework import generics
|
||||
from rest_framework import generics, mixins
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from .serializers import StudyGroupSerializer
|
||||
|
@ -11,6 +11,8 @@ from django.contrib.gis.geos import fromstr
|
|||
from django.contrib.gis.db.models.functions import Distance
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import permissions
|
||||
|
||||
# Create your views here.
|
||||
|
||||
|
||||
|
@ -19,45 +21,6 @@ class StudyGroupListView(generics.ListCreateAPIView, generics.UpdateAPIView, gen
|
|||
serializer_class = StudyGroupSerializer
|
||||
queryset = StudyGroup.objects.all()
|
||||
|
||||
def partial_update(self, instance, request, *args, **kwargs):
|
||||
# Ensure only "users" field is being updated
|
||||
if set(request.data.keys()) != {"users"}:
|
||||
return Response({"detail": "Only the 'users' field can be updated."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Get the current list of users
|
||||
instance = self.get_object()
|
||||
current_users = set(instance.users.values_list('id', flat=True))
|
||||
|
||||
# Get the new list of users from the request
|
||||
new_users = set(request.data['users'])
|
||||
|
||||
# Check if the only difference between the two sets is the current user
|
||||
diff = current_users.symmetric_difference(new_users)
|
||||
if len(diff) > 1 or (len(diff) == 1 and request.user.id not in diff):
|
||||
return Response({"detail": "You can only add or remove yourself from the study group."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Delete the study group if there are no users left
|
||||
instance = self.get_object()
|
||||
if not instance.users.exists():
|
||||
instance.delete()
|
||||
|
||||
return super().partial_update(request, *args, **kwargs)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
|
||||
# Check if the current user is the creator of the study group
|
||||
# Assuming 'date_joined' is a field in your User model
|
||||
creator = instance.users.all().first()
|
||||
if request.user != creator:
|
||||
return Response({"detail": "Only the creator can delete the study group."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Check if the current user is the only one in the study group
|
||||
if instance.users.count() > 1:
|
||||
return Response({"detail": "The study group cannot be deleted if there are other users in it."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
user = self.request.user
|
||||
|
||||
|
@ -145,6 +108,7 @@ class StudyGroupListNearView(generics.ListAPIView):
|
|||
return studygroups
|
||||
|
||||
|
||||
class StudyGroupMembershipViewSet(generics.ListAPIView):
|
||||
serializer_class = StudyGroupSerializer
|
||||
queryset = StudyGroup.objects.all()
|
||||
class IsOwnerOrReadOnly(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj):
|
||||
# Check if the requesting user's student status matches the user field
|
||||
return obj.user == request.user.studentstatus
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue