diff --git a/csoc_backend/settings/base.py b/csoc_backend/settings/base.py index fdb2ab0..d0fcd9e 100644 --- a/csoc_backend/settings/base.py +++ b/csoc_backend/settings/base.py @@ -22,6 +22,7 @@ 'task', 'rest_framework', 'rest_framework_simplejwt', + 'learning_resources', ] MIDDLEWARE = [ @@ -85,7 +86,8 @@ # token settings SIMPLE_JWT = { - 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), # Adjust token lifetime as needed + # Adjust token lifetime as needed + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=1000), 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), 'SLIDING_TOKEN_REFRESH_LIFETIME_GRACE_PERIOD': timedelta(days=1), 'SLIDING_TOKEN_REFRESH_REVOKE_ON_PASSWORD_CHANGE': True, @@ -99,7 +101,6 @@ } - # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/ diff --git a/csoc_backend/urls.py b/csoc_backend/urls.py index 263bdda..d1c99a8 100644 --- a/csoc_backend/urls.py +++ b/csoc_backend/urls.py @@ -20,7 +20,8 @@ # users API path('dsa/', include('dsa.urls')), path('user/', include('user.apis.urls')), - path('task/', include('task.urls')) - ]), + path('task/', include('task.urls')), + path('resources/', include('learning_resources.urls')), + ]), ), ] diff --git a/learning_resources/__init__.py b/learning_resources/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/learning_resources/admin.py b/learning_resources/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/learning_resources/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/learning_resources/apps.py b/learning_resources/apps.py new file mode 100644 index 0000000..2185a15 --- /dev/null +++ b/learning_resources/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class LearningResourcesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'learning_resources' diff --git a/learning_resources/migrations/0001_initial.py b/learning_resources/migrations/0001_initial.py new file mode 100644 index 0000000..293de8d --- /dev/null +++ b/learning_resources/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.2 on 2023-07-27 19:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Resource', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('domain', models.CharField(choices=[('dsa', 'DSA'), ('web', 'Web'), ('app', 'App'), ('ui', 'UI/UX')], max_length=3)), + ('topic', models.CharField(max_length=100)), + ('name', models.CharField(max_length=100)), + ('link', models.URLField()), + ], + ), + ] diff --git a/learning_resources/migrations/0002_rename_name_resource_description_and_more.py b/learning_resources/migrations/0002_rename_name_resource_description_and_more.py new file mode 100644 index 0000000..5c11777 --- /dev/null +++ b/learning_resources/migrations/0002_rename_name_resource_description_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.2 on 2023-07-28 17:44 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('user', '0011_rename_team_invite_team_alter_inquiry_email_and_more'), + ('learning_resources', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='resource', + old_name='name', + new_name='description', + ), + migrations.RemoveField( + model_name='resource', + name='domain', + ), + migrations.AddField( + model_name='resource', + name='program', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='user.program'), + preserve_default=False, + ), + ] diff --git a/learning_resources/migrations/__init__.py b/learning_resources/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/learning_resources/models.py b/learning_resources/models.py new file mode 100644 index 0000000..ea3e9ab --- /dev/null +++ b/learning_resources/models.py @@ -0,0 +1,12 @@ +from django.db import models + +from user.models import Program + +class Resource(models.Model): + program = models.ForeignKey(Program, on_delete=models.CASCADE) + topic = models.CharField(max_length=100) + description = models.CharField(max_length=100) + link = models.URLField() + + def __str__(self): + return self.topic diff --git a/learning_resources/serializers.py b/learning_resources/serializers.py new file mode 100644 index 0000000..1b12683 --- /dev/null +++ b/learning_resources/serializers.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + +from .models import Resource + + +class ResourceSerializer(serializers.ModelSerializer): + class Meta: + model = Resource + fields = ('program', 'topic', 'description', 'link') diff --git a/learning_resources/tests.py b/learning_resources/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/learning_resources/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/learning_resources/urls.py b/learning_resources/urls.py new file mode 100644 index 0000000..bd7fe84 --- /dev/null +++ b/learning_resources/urls.py @@ -0,0 +1,8 @@ +from django.urls import path + +from .views import ResourceListAPIView + + +urlpatterns = [ + path('', ResourceListAPIView.as_view(), name='resource_list'), +] diff --git a/learning_resources/views.py b/learning_resources/views.py new file mode 100644 index 0000000..1445e74 --- /dev/null +++ b/learning_resources/views.py @@ -0,0 +1,38 @@ +from rest_framework.generics import ListAPIView +from rest_framework_simplejwt.authentication import JWTAuthentication +from rest_framework.response import Response +from collections import defaultdict + +from .models import Resource +from .serializers import ResourceSerializer +from user.apis.permissions import CustomPermissionMixin + + +class ResourceListAPIView(CustomPermissionMixin, ListAPIView): + queryset = Resource.objects.all() + serializer_class = ResourceSerializer + authentication_classes = [JWTAuthentication] + + + def get_resource_data(self, resource_data): + return { + "description": resource_data['description'], + "link": resource_data['link'], + } + + def generate_grouped_resources(self): + resources = Resource.objects.values('program__name', 'topic', 'description', 'link') + grouped_resources = defaultdict(lambda: defaultdict(list)) + [ + grouped_resources[resource_data['program__name']][resource_data['topic']].append(self.get_resource_data(resource_data)) + for resource_data in resources + ] + return grouped_resources + + def get(self, request, *args, **kwargs): + grouped_resources = self.generate_grouped_resources() + response_data = { + program_name: [{"topic": topic, "resources": resources_list} for topic, resources_list in topics.items()] + for program_name, topics in grouped_resources.items() + } + return Response(response_data) diff --git a/requirements.txt b/requirements.txt index 41d5ded..81e0be3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ phonenumbers==8.13.14 python-dotenv==1.0.0 loguru djangorestframework -djangorestframework-simplejwt \ No newline at end of file +djangorestframework-simplejwt +pandas \ No newline at end of file diff --git a/user/apis/views.py b/user/apis/views.py index 19aaa93..6036b55 100644 --- a/user/apis/views.py +++ b/user/apis/views.py @@ -2,9 +2,3 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -@api_view(['GET']) -@permission_classes([IsAuthenticated]) -def protected_view(request): - user = request.user - # Your logic for the protected view - return Response({'message': f'Hello, {user.username}! This is a protected view.'})