Add API support

This commit is contained in:
Valentin Moguérou 2024-05-05 21:24:44 +02:00
parent 54de82af42
commit fe1914b5a5
6 changed files with 266 additions and 2 deletions

View File

@ -148,7 +148,8 @@ class Term(models.Model):
.annotate(base_vol=Count("groups__members")) .annotate(base_vol=Count("groups__members"))
.annotate(swap_plus=Count("swap", filter=Q(swap__enroll=1), distinct=True)) .annotate(swap_plus=Count("swap", filter=Q(swap__enroll=1), distinct=True))
.annotate(swap_minus=Count("swap", filter=Q(swap__enroll=0), distinct=True)) .annotate(swap_minus=Count("swap", filter=Q(swap__enroll=0), distinct=True))
.annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus"))) .annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus"))
.order_by())
def query_colles_of_student(self, student) -> QuerySet: def query_colles_of_student(self, student) -> QuerySet:
has_student = ((Q(groups__student=student) has_student = ((Q(groups__student=student)
@ -164,6 +165,7 @@ class Term(models.Model):
.annotate(swap_minus=Count("pk", filter=Q(swap__enroll=0), distinct=True)) .annotate(swap_minus=Count("pk", filter=Q(swap__enroll=0), distinct=True))
.annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus")) .annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus"))
.filter(has_student) .filter(has_student)
.order_by()
) )
def query_colles_not_full_excluding_student(self, student) -> QuerySet: def query_colles_not_full_excluding_student(self, student) -> QuerySet:
@ -184,6 +186,9 @@ class Subject(models.Model):
description = models.CharField(max_length=100) description = models.CharField(max_length=100)
code = models.CharField(max_length=20) code = models.CharField(max_length=20)
class Meta:
ordering = ["description"]
def __str__(self): def __str__(self):
return self.description return self.description
@ -292,6 +297,7 @@ class Slot(models.Model):
capacity = models.IntegerField() capacity = models.IntegerField()
class Meta: class Meta:
ordering = ["subject", "colleur", "day", "time"]
verbose_name_plural = "slots" verbose_name_plural = "slots"
def __str__(self): def __str__(self):

73
colloscope/serializers.py Normal file
View File

@ -0,0 +1,73 @@
from rest_framework.serializers import ModelSerializer
from colloscope.models import *
class SchoolSerializer(ModelSerializer):
class Meta:
model = School
fields = ["id", "uai", "description", "vacation"]
class StudentSerializer(ModelSerializer):
class Meta:
model = Student
fields = ["id", "cls", "first_name", "last_name", "groups"]
class ClassSerializer(ModelSerializer):
students = StudentSerializer(source="student_set", many=True)
class Meta:
model = Class
fields = ["id", "school", "description", "year", "day_zero", "students"]
class TermSerializer(ModelSerializer):
class Meta:
model = Term
fields = ["id", "cls", "description", "begin", "end"]
class SubjectSerializer(ModelSerializer):
class Meta:
model = Subject
fields = ["id", "cls", "description", "code"]
class GroupTypeSerializer(ModelSerializer):
class Meta:
model = GroupType
fields = ["id", "term", "description"]
class GroupSerializer(ModelSerializer):
class Meta:
model = Group
fields = ["id", "term", "description", "members"]
class ColleurSerializer(ModelSerializer):
class Meta:
model = Colleur
fields = ["id", "gender", "name"]
class SlotSerializer(ModelSerializer):
class Meta:
model = Slot
fields = ["id", "term", "day", "time", "duration", "room", "subject", "colleur", "type", "capacity"]
class ColleSerializer(ModelSerializer):
class Meta:
model = Colle
fields = ["id", "slot", "groups", "date"]
class CalendarLinkSerializer(ModelSerializer):
class Meta:
model = CalendarLink
fields = ["id", "key", "student", "term"]

82
colloscope/viewsets.py Normal file
View File

@ -0,0 +1,82 @@
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from colloscope.models import *
from colloscope.serializers import *
class SchoolViewset(ReadOnlyModelViewSet):
serializer_class = SchoolSerializer
def get_queryset(self):
return School.objects.all()
class ClassViewset(ReadOnlyModelViewSet):
serializer_class = ClassSerializer
def get_queryset(self):
return Class.objects.all()
class TermViewset(ReadOnlyModelViewSet):
serializer_class = TermSerializer
def get_queryset(self):
return Term.objects.all()
class SubjectViewset(ReadOnlyModelViewSet):
serializer_class = SubjectSerializer
def get_queryset(self):
return Subject.objects.all()
class GroupTypeViewset(ReadOnlyModelViewSet):
serializer_class = GroupTypeSerializer
def get_queryset(self):
return GroupType.objects.all()
class GroupViewset(ReadOnlyModelViewSet):
serializer_class = GroupSerializer
def get_queryset(self):
return Group.objects.all()
class StudentViewset(ReadOnlyModelViewSet):
serializer_class = StudentSerializer
def get_queryset(self):
return Student.objects.all()
class ColleurViewset(ReadOnlyModelViewSet):
serializer_class = ColleurSerializer
def get_queryset(self):
return Colleur.objects.all()
class SlotViewset(ReadOnlyModelViewSet):
serializer_class = SlotSerializer
def get_queryset(self):
return Slot.objects.all()
class ColleViewset(ReadOnlyModelViewSet):
serializer_class = ColleSerializer
def get_queryset(self):
return Colle.objects.all()
class CalendarLinkViewset(ReadOnlyModelViewSet):
serializer_class = CalendarLinkSerializer
def get_queryset(self):
return CalendarLink.objects.all()

View File

@ -42,16 +42,21 @@ CORS_ORIGIN_WHITELIST = [
INSTALLED_APPS = [ INSTALLED_APPS = [
"daphne", "daphne",
'django.contrib.admin', 'django.contrib.admin',
'oauth2_provider',
'corsheaders',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
"rest_framework",
'colloscope', 'colloscope',
"drf_spectacular",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@ -163,4 +168,20 @@ EMAIL_HOST = "pulp.o2switch.net"
EMAIL_PORT = 587 EMAIL_PORT = 587
EMAIL_HOST_USER = "colloscope@mp2i-vms.fr" EMAIL_HOST_USER = "colloscope@mp2i-vms.fr"
EMAIL_HOST_PASSWORD = "phoBTchc2vVaq$PefsntT9M7" EMAIL_HOST_PASSWORD = "phoBTchc2vVaq$PefsntT9M7"
EMAIL_USE_TLS = True EMAIL_USE_TLS = True
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
'PAGE_SIZE': 10,
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
SPECTACULAR_SETTINGS = {
'TITLE': 'Colloscope API',
'DESCRIPTION': 'Gérer les colles de prépa devient facile',
'VERSION': '1.0.0',
'SERVE_INCLUDE_SCHEMA': False,
# OTHER SETTINGS
}

View File

@ -17,11 +17,35 @@ Including another URLconf
from django.contrib import admin, auth from django.contrib import admin, auth
from django.urls import include, path from django.urls import include, path
from django.contrib.staticfiles import views as vstatic from django.contrib.staticfiles import views as vstatic
from rest_framework import routers
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
from colloscope.views import home_redirect from colloscope.views import home_redirect
from colloscope.viewsets import *
router = routers.SimpleRouter()
router.register('school', SchoolViewset, basename='school')
router.register('class', ClassViewset, basename='class')
router.register('term', TermViewset, basename='term')
router.register("subject", SubjectViewset, basename='subject')
router.register('grouptype', GroupTypeViewset, basename='grouptype')
router.register("group", GroupViewset, basename='group')
router.register("student", StudentViewset, basename='student')
router.register("colleur", ColleurViewset, basename='colleur')
router.register("slot", SlotViewset, basename='slot')
router.register("colle", ColleViewset, basename='colle')
router.register("calendarlink", CalendarLinkViewset, basename='calendarlink')
urlpatterns = [ urlpatterns = [
path('', home_redirect, name="home"), path('', home_redirect, name="home"),
path('api-auth/', include('rest_framework.urls')),
path("api/", include(router.urls)),
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
path("oauth2/", include('oauth2_provider.urls', namespace='oauth2_provider')),
path("favicon.ico", lambda req: vstatic.serve(req, "favicon.ico")), path("favicon.ico", lambda req: vstatic.serve(req, "favicon.ico")),
path('colloscope/', include('colloscope.urls')), path('colloscope/', include('colloscope.urls')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),

58
requirements.txt Normal file
View File

@ -0,0 +1,58 @@
aiohttp==3.9.5
aiosignal==1.3.1
asgiref==3.8.1
attrs==23.2.0
autobahn==23.6.2
Automat==22.10.0
certifi==2024.2.2
cffi==1.16.0
charset-normalizer==3.3.2
constantly==23.10.4
cryptography==42.0.5
daphne==4.1.2
defusedxml==0.7.1
discord.py==2.3.2
Django==5.0.4
django-cors-headers==4.3.1
django-oauth-toolkit==2.3.0
django-smtp-ssl==1.0
djangorestframework==3.15.1
drf-spectacular==0.27.2
fonttools==4.51.0
fpdf2==2.7.8
frozenlist==1.4.1
hyperlink==21.0.0
icalendar==5.0.12
idna==3.7
incremental==22.10.0
inflection==0.5.1
jsonschema==4.22.0
jsonschema-specifications==2023.12.1
jwcrypto==1.5.6
multidict==6.0.5
numpy==1.26.4
oauthlib==3.2.2
pandas==2.2.2
pillow==10.3.0
pyasn1==0.6.0
pyasn1_modules==0.4.0
pycparser==2.22
pyOpenSSL==24.1.0
python-dateutil==2.9.0.post0
pytz==2024.1
PyYAML==6.0.1
referencing==0.35.1
requests==2.31.0
rpds-py==0.18.0
service-identity==24.1.0
setuptools==69.5.1
six==1.16.0
sqlparse==0.4.4
Twisted==24.3.0
txaio==23.1.1
typing_extensions==4.11.0
tzdata==2024.1
uritemplate==4.1.1
urllib3==2.2.1
yarl==1.9.4
zope.interface==6.3