Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/csv file upload #17

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions socbackend/accounts/custom_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@

class CookieJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
header = None
token = None
user = None
try:
header = super().authenticate(request)
user, token = super().authenticate(request)
# print({user, token})
except Exception as e:
logger.debug(f"Header login failed: {e}")


if header is None:
if token is None:
# Attempt to get token from the cookie
token = request.COOKIES.get("auth")
if token:
return self.get_user(self.get_validated_token(token)), None

return header, None
return user, token
1 change: 1 addition & 0 deletions socbackend/projects/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
path("<int:pk>/", views.ProjectDetailView.as_view(), name="project_detail"),
path("wishlist/", views.ProjectWishlist.as_view(), name="wishlist"),
path("preference/", views.ProjectPreference.as_view(), name="prefenrence"),
path('upload/', views.FileUploadView.as_view(), name='upload')

# path("add/", views.ProjectAddView.as_view(), name="project_add"),
]
77 changes: 76 additions & 1 deletion socbackend/projects/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

# from projects.models import Season
from accounts.custom_auth import CookieJWTAuthentication
from rest_framework import generics, views
from rest_framework import generics, views, status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Mentee, Project, MenteePreference, MenteeWishlist
from rest_framework.permissions import IsAuthenticated
from accounts.models import UserProfile
from rest_framework.permissions import AllowAny
import logging
import os
import csv

logger = logging.getLogger(__name__)
# from .serializers import (
Expand Down Expand Up @@ -106,6 +108,79 @@ def delete(self, request):
preference = MenteePreference.objects.get(mentee=mentee, project=project)
preference.delete()
return Response({"message": "Project removed from preferences."})

class FileUploadView(APIView):
authentication_classes = [CookieJWTAuthentication]

EXPECTED_HEADERS = ['id','mentor','title','co_mentor_info','specific_category','description','mentee_max','prereuisites','banner_image','banner_image_link','timeline','checkpoints','general_category']

def post(self, request, *args, **kwargs):
try:
uploaded_file = request.FILES.get('file')
# print("Uploaded file:", uploaded_file)

if not uploaded_file:
return Response({
'message': 'No file uploaded.'
}, status=status.HTTP_400_BAD_REQUEST)

file_extension = os.path.splitext(uploaded_file.name)[1]
if file_extension.lower() != '.csv':
return Response({
'message': 'Unsupported file. Upload only csv file'
}, status=status.HTTP_400_BAD_REQUEST)


# read csv file directly from memory
csv_reader = csv.DictReader(uploaded_file.read().decode('utf-8').splitlines())
headers = []

is_header_checked = False

for idx, row in enumerate(csv_reader):
if not is_header_checked:
headers = list(row.keys())
is_header_checked = True
if headers != self.EXPECTED_HEADERS:
raise Exception('Headers mistach: csv file headers corrupted')

try:
project, created = Project.objects.get_or_create(
title=row['title'].strip(),
mentor=row['mentor'].strip(),
defaults={
'co_mentor_info': row['co_mentor_info'],
'specific_category': row['specific_category'],
'description': row['description'],
'mentee_max': int(row['mentee_max']),
'prereuisites': row['prereuisites'],
'banner_image_link': row['banner_image_link'],
'timeline': row['timeline'],
'checkpoints': row['checkpoints'],
'general_category': row['general_category'],
'banner_image': row['banner_image']
}
)

if created:
project.save()
print(f'new entry created for {project.title}')
else:
logger.error(f'project {project.code} already exists')

except Exception as e:
logger.error(f'database error for {row['title']}: {e}')

return Response({
'message': 'File upload successful'
}, status=status.HTTP_200_OK)

except Exception as e:
logger.error(f'error: {e}')
# print('error: ', e)
return Response({
'message': 'Corrupted file'
}, status=status.HTTP_400_BAD_REQUEST)

class BasicProjectListView(generics.ListAPIView):
permission_classes = []
Expand Down