Initial Commit
This commit is contained in:
parent
dcc4a10f6e
commit
aa9aa40e81
|
@ -1,4 +1,3 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
|
@ -127,3 +126,12 @@ dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
|
|
||||||
|
/venv/
|
||||||
|
/.github/
|
||||||
|
/CDC_Backend/CDC_Backend/__pycache__/
|
||||||
|
/CDC_Backend/APIs/__pycache__/
|
||||||
|
/CDC_Backend/APIs/migrations/
|
||||||
|
.idea
|
||||||
|
*.pyc
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
from .models import *
|
||||||
|
|
||||||
|
admin.site.register(User)
|
||||||
|
admin.site.register(Student)
|
||||||
|
admin.site.register(PR)
|
||||||
|
admin.site.register(Company)
|
||||||
|
admin.site.register(Placement)
|
||||||
|
admin.site.register(Internship)
|
||||||
|
admin.site.register(PlacementApplication)
|
||||||
|
admin.site.register(InternshipApplication)
|
||||||
|
admin.site.register(PrePlacementOffer)
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.urls import path
|
||||||
|
from . import companyViews
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
|
||||||
|
]
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApisConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'APIs'
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.urls import path
|
||||||
|
from . import companyViews
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('addOpening/', companyViews.addOpening, name="Add Opening"),
|
||||||
|
]
|
|
@ -0,0 +1,120 @@
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.utils.timezone import make_aware
|
||||||
|
from rest_framework.decorators import api_view
|
||||||
|
|
||||||
|
from .utils import *
|
||||||
|
|
||||||
|
logger = logging.getLogger('db')
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@precheck([OPENING_DESIGNATION, OPENING_DESCRIPTION, OPENING_TYPE, OPENING_CITY, OPENING_CITY_TYPE,
|
||||||
|
OPENING_COMPENSATION, OPENING_COMPENSATION_DETAILS, OPENING_ALLOWED_BATCH, OPENING_ALLOWED_BRANCH,
|
||||||
|
OPENING_ROUNDS, OPENING_CO_OP, OPENING_START_DATE, OPENING_ADDITIONAL_INFO,
|
||||||
|
OPENING_DURATION, OPENING_ROUND_DETAILS])
|
||||||
|
def addOpening(request):
|
||||||
|
try:
|
||||||
|
data = request.data
|
||||||
|
if data[OPENING_TYPE] == "Placement":
|
||||||
|
opening = Placement()
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid Opening Type")
|
||||||
|
|
||||||
|
opening.id = generateRandomString()
|
||||||
|
# Create Company object here for every Opening
|
||||||
|
|
||||||
|
|
||||||
|
# Some new code above
|
||||||
|
|
||||||
|
if data[OPENING_DESIGNATION] != "":
|
||||||
|
opening.designation = data[OPENING_DESIGNATION]
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_DESIGNATION + " Not Found")
|
||||||
|
|
||||||
|
opening.description = data[OPENING_DESCRIPTION]
|
||||||
|
|
||||||
|
if data[OPENING_START_DATE] != "":
|
||||||
|
opening.description = data[OPENING_START_DATE]
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_START_DATE + " Not Found")
|
||||||
|
if data[OPENING_START_DATE] != "":
|
||||||
|
opening.start_date = datetime.strptime(data[OPENING_START_DATE], '%d-%m-%Y')
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_START_DATE + " Not Found")
|
||||||
|
if data[OPENING_CITY] != "":
|
||||||
|
opening.city = data[OPENING_CITY]
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_CITY + " Not Found")
|
||||||
|
if data[OPENING_CITY_TYPE] != "":
|
||||||
|
opening.city_type = data[OPENING_CITY_TYPE]
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_CITY_TYPE + " Not Found")
|
||||||
|
if data[OPENING_COMPENSATION] != "":
|
||||||
|
opening.compensation = data[OPENING_COMPENSATION]
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_COMPENSATION + " Not Found")
|
||||||
|
|
||||||
|
opening.compensation_details = data[OPENING_COMPENSATION_DETAILS]
|
||||||
|
|
||||||
|
if data[OPENING_ALLOWED_BATCH] != "":
|
||||||
|
if set(json.loads(data[OPENING_ALLOWED_BATCH])).issubset(BATCHES):
|
||||||
|
opening.allowed_batch = json.loads(data[OPENING_ALLOWED_BATCH])
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_ALLOWED_BATCH + " is Invalid")
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_ALLOWED_BATCH + " Not Found")
|
||||||
|
if data[OPENING_ALLOWED_BRANCH] != "":
|
||||||
|
if set(json.loads(data[OPENING_ALLOWED_BRANCH])).issubset(BRANCHES):
|
||||||
|
opening.allowed_branch = json.loads(data[OPENING_ALLOWED_BRANCH])
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_ALLOWED_BATCH + " is Invalid")
|
||||||
|
else:
|
||||||
|
raise ValueError(OPENING_ALLOWED_BRANCH + " Not Found")
|
||||||
|
|
||||||
|
opening.rounds = json.loads(data[OPENING_ROUNDS])
|
||||||
|
|
||||||
|
opening.additional_info = json.loads(data[OPENING_ADDITIONAL_INFO])
|
||||||
|
|
||||||
|
opening.status = STATUS_ACCEPTING_APPLICATIONS
|
||||||
|
|
||||||
|
opening.rounds_details = json.loads(data[OPENING_ROUND_DETAILS])
|
||||||
|
|
||||||
|
opening.created_at = make_aware(datetime.now())
|
||||||
|
files = request.FILES.getlist(OPENING_ATTACHMENTS)
|
||||||
|
attachments = []
|
||||||
|
for file in files:
|
||||||
|
attachments.append(saveFile(file, STORAGE_DESTINATION_COMPANY_ATTACHMENTS))
|
||||||
|
|
||||||
|
opening.attachments = attachments
|
||||||
|
opening.save()
|
||||||
|
data = {
|
||||||
|
"designation": opening.designation,
|
||||||
|
"opening_type": data[OPENING_TYPE],
|
||||||
|
"opening_link": "google.com", # Some Changes here too
|
||||||
|
"company_name": opening.company.name
|
||||||
|
}
|
||||||
|
|
||||||
|
# Needs some edits here
|
||||||
|
|
||||||
|
email = 'This is temporary'
|
||||||
|
|
||||||
|
# Delete the above var when done
|
||||||
|
|
||||||
|
stat = sendEmail(email, COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT.format(id=opening.id), data,
|
||||||
|
COMPANY_OPENING_SUBMITTED_TEMPLATE)
|
||||||
|
if stat is not True:
|
||||||
|
logger.warning("Add New Opening: Unable to send email - " + stat)
|
||||||
|
|
||||||
|
return Response({'action': "Add Opening", 'message': "Opening Added"},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
except ValueError as e:
|
||||||
|
return Response({'action': "Add Opening", 'message': str(e)},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
except:
|
||||||
|
logger.warning("Add New Opening: " + str(sys.exc_info()))
|
||||||
|
return Response({'action': "Add Opening", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
|
@ -0,0 +1,92 @@
|
||||||
|
BRANCH_CHOICES = [
|
||||||
|
["CSE", "CSE"],
|
||||||
|
["EE", "EE"],
|
||||||
|
["ME", "ME"]
|
||||||
|
]
|
||||||
|
|
||||||
|
BATCH_CHOICES = [
|
||||||
|
["FIRST", "First"],
|
||||||
|
["SECOND", "Second"],
|
||||||
|
["THIRD", "Third"],
|
||||||
|
["FOURTH", "Fourth"]
|
||||||
|
]
|
||||||
|
|
||||||
|
OFFER_CITY_TYPE = [
|
||||||
|
['Domestic', 'Domestic'],
|
||||||
|
['International', 'International']
|
||||||
|
]
|
||||||
|
|
||||||
|
TIERS = [
|
||||||
|
['psu', 'PSU'],
|
||||||
|
['1', 'Tier 1'],
|
||||||
|
['2', 'Tier 2'],
|
||||||
|
['3', 'Tier 3'],
|
||||||
|
['4', 'Tier 4'],
|
||||||
|
['5', 'Tier 5'],
|
||||||
|
['6', 'Tier 6']
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
TOTAL_BRANCHES = 3 # Total No of Branches
|
||||||
|
TOTAL_BATCHES = 4 # Total No of Batches
|
||||||
|
|
||||||
|
CLIENT_ID = "956830229554-290mirc16pdhd5j7ph7v7ukibo4t1qcp.apps.googleusercontent.com" # Google Login Client ID
|
||||||
|
|
||||||
|
TOKEN = "token_id"
|
||||||
|
EMAIL = "email"
|
||||||
|
|
||||||
|
STUDENT = 'student'
|
||||||
|
ADMIN = 'Admin'
|
||||||
|
COMPANY = ''
|
||||||
|
STORAGE_DESTINATION = "./Storage/Resumes/"
|
||||||
|
STORAGE_DESTINATION_COMPANY_ATTACHMENTS = './Storage/Company_Attachments/'
|
||||||
|
|
||||||
|
RESUME_FILE_NAME = 'resume_file_name'
|
||||||
|
|
||||||
|
APPLICATION_ID = "application_id"
|
||||||
|
APPLICATION_OPENING_TYPE = "opening_type"
|
||||||
|
APPLICATION_OPENING_ID = "opening_id"
|
||||||
|
APPLICATION_ADDITIONAL_INFO = "additional_info"
|
||||||
|
|
||||||
|
STATUS_ACCEPTING_APPLICATIONS = "Accepting Applications"
|
||||||
|
|
||||||
|
PLACEMENT = "Placement"
|
||||||
|
|
||||||
|
COMPANY_WEBSITE = 'website'
|
||||||
|
COMPANY_ADDRESS = 'address'
|
||||||
|
COMPANY_PHONE_NUMBER = 'phone_number'
|
||||||
|
COMPANY_CONTACT_PERSON_NAME = 'contact_person_name'
|
||||||
|
|
||||||
|
OPENING_DESIGNATION = 'designation'
|
||||||
|
OPENING_DESCRIPTION = 'description'
|
||||||
|
OPENING_TYPE = 'opening_type'
|
||||||
|
OPENING_CITY = 'city'
|
||||||
|
OPENING_CITY_TYPE = 'city_type'
|
||||||
|
OPENING_COMPENSATION = 'compensation'
|
||||||
|
OPENING_COMPENSATION_DETAILS = 'compensation_details'
|
||||||
|
OPENING_ALLOWED_BATCH = 'allowed_batch'
|
||||||
|
OPENING_ALLOWED_BRANCH = 'allowed_branch'
|
||||||
|
OPENING_ATTACHMENTS = 'attachments'
|
||||||
|
OPENING_ROUNDS = 'rounds'
|
||||||
|
OPENING_ADDITIONAL_INFO = 'additional_info'
|
||||||
|
OPENING_ROUND_DETAILS = 'round_details'
|
||||||
|
OPENING_DURATION = 'duration'
|
||||||
|
OPENING_CO_OP = 'co_op'
|
||||||
|
OPENING_START_DATE = 'start_date'
|
||||||
|
|
||||||
|
BRANCHES = [
|
||||||
|
"CSE",
|
||||||
|
"EE",
|
||||||
|
"ME"
|
||||||
|
]
|
||||||
|
BATCHES = [
|
||||||
|
"FIRST",
|
||||||
|
"SECOND",
|
||||||
|
"THIRD",
|
||||||
|
"FOURTH"
|
||||||
|
]
|
||||||
|
|
||||||
|
COMPANY_OPENING_SUBMITTED_TEMPLATE_SUBJECT = "Notification Submitted - {id} - CDC IIT Dharwad"
|
||||||
|
|
||||||
|
STUDENT_APPLICATION_SUBMITTED_TEMPLATE = 'student_application_submitted.html'
|
||||||
|
COMPANY_OPENING_SUBMITTED_TEMPLATE = 'company_opening_submitted.html'
|
|
@ -0,0 +1,103 @@
|
||||||
|
from django.contrib.postgres.fields import ArrayField
|
||||||
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
|
from .constants import *
|
||||||
|
|
||||||
|
|
||||||
|
class User(models.Model):
|
||||||
|
email = models.CharField(primary_key=True, blank=False, max_length=50)
|
||||||
|
id = models.CharField(blank=False, max_length=25)
|
||||||
|
user_type = ArrayField(models.CharField(blank=False, max_length=10), size=4, default=list, blank=False)
|
||||||
|
|
||||||
|
|
||||||
|
class Student(models.Model):
|
||||||
|
id = models.CharField(blank=False, max_length=15, primary_key=True)
|
||||||
|
roll_no = models.IntegerField(blank=False)
|
||||||
|
name = models.CharField(blank=False, max_length=50)
|
||||||
|
batch = models.CharField(max_length=10, choices=BATCH_CHOICES, blank=False)
|
||||||
|
branch = models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10)
|
||||||
|
phone_number = models.PositiveBigIntegerField(blank=True, default=None, null=True)
|
||||||
|
resumes = ArrayField(models.CharField(null=True, default=None, max_length=100), size=10, default=list, blank=True)
|
||||||
|
cpi = models.DecimalField(decimal_places=2, max_digits=4)
|
||||||
|
|
||||||
|
|
||||||
|
class Admin(models.Model):
|
||||||
|
id = models.CharField(blank=False, max_length=15, primary_key=True)
|
||||||
|
name = models.CharField(blank=False, max_length=50)
|
||||||
|
|
||||||
|
|
||||||
|
class Placement(models.Model):
|
||||||
|
id = models.CharField(blank=False, primary_key=True, max_length=15)
|
||||||
|
name = models.CharField(blank=False, max_length=50)
|
||||||
|
address = models.CharField(blank=False, max_length=150)
|
||||||
|
companyType = models.CharField(blank=False, max_length=50)
|
||||||
|
website = models.CharField(blank=True, max_length=50)
|
||||||
|
contact_person_name = models.CharField(blank=False, max_length=50)
|
||||||
|
phone_number = models.PositiveBigIntegerField(blank=False)
|
||||||
|
designation = models.CharField(blank=False, max_length=25, default=None, null=True)
|
||||||
|
description = models.CharField(blank=False, max_length=200)
|
||||||
|
start_date = models.DateField(blank=False, verbose_name="Start Date")
|
||||||
|
city = models.CharField(blank=False, max_length=100, default="")
|
||||||
|
city_type = models.CharField(blank=False, max_length=15, choices=OFFER_CITY_TYPE)
|
||||||
|
compensation = models.IntegerField(blank=False) # Job - Per Year
|
||||||
|
compensation_details = models.CharField(blank=True, max_length=200)
|
||||||
|
tier = models.CharField(blank=False, choices=TIERS, max_length=10, default=None, null=True)
|
||||||
|
allowed_batch = ArrayField(
|
||||||
|
models.CharField(max_length=10, choices=BATCH_CHOICES),
|
||||||
|
size=TOTAL_BATCHES,
|
||||||
|
default=list
|
||||||
|
)
|
||||||
|
allowed_branch = ArrayField(
|
||||||
|
models.CharField(choices=BRANCH_CHOICES, blank=False, max_length=10),
|
||||||
|
size=TOTAL_BRANCHES,
|
||||||
|
default=list
|
||||||
|
)
|
||||||
|
attachments = ArrayField(
|
||||||
|
models.CharField(max_length=100, blank=True),
|
||||||
|
size=10,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
rounds = ArrayField(
|
||||||
|
models.CharField(max_length=25, blank=True),
|
||||||
|
size=10,
|
||||||
|
)
|
||||||
|
additional_info = ArrayField(
|
||||||
|
models.CharField(max_length=25, blank=True),
|
||||||
|
size=10,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
status = models.CharField(max_length=50, blank=False)
|
||||||
|
rounds_details = models.JSONField(blank=True, default=dict)
|
||||||
|
created_at = models.DateTimeField(blank=False, default=None, null=True)
|
||||||
|
|
||||||
|
|
||||||
|
class PlacementApplication(models.Model):
|
||||||
|
id = models.CharField(blank=False, primary_key=True, max_length=15)
|
||||||
|
placement = models.ForeignKey(Placement, blank=False, on_delete=models.RESTRICT, default=None, null=True)
|
||||||
|
student = models.ForeignKey(Student, blank=False, on_delete=models.CASCADE)
|
||||||
|
resume = models.CharField(max_length=100, blank=False, null=True, default=None)
|
||||||
|
status = models.CharField(max_length=50, null=True, blank=True, default=None)
|
||||||
|
additional_info = models.JSONField(blank=True, default=None, null=True)
|
||||||
|
selected = models.BooleanField(null=True, default=None, blank=True)
|
||||||
|
applied_at = models.DateTimeField(blank=False, default=None, null=True)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
''' On save, add timestamps '''
|
||||||
|
if not self.applied_at:
|
||||||
|
self.applied_at = timezone.now()
|
||||||
|
|
||||||
|
return super(PlacementApplication, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name_plural = "Placement Applications"
|
||||||
|
|
||||||
|
|
||||||
|
class PrePlacementOffer(models.Model):
|
||||||
|
id = models.AutoField(primary_key=True)
|
||||||
|
student = models.ForeignKey(Student, on_delete=models.CASCADE, blank=False)
|
||||||
|
company = models.CharField(max_length=50, blank=False)
|
||||||
|
compensation = models.IntegerField(blank=False) # Job - Per Year
|
||||||
|
compensation_details = models.CharField(blank=True, max_length=200)
|
||||||
|
tier = models.CharField(blank=False, choices=TIERS, max_length=10)
|
||||||
|
designation = models.CharField(blank=False, max_length=25, default=None, null=True)
|
||||||
|
accepted = models.BooleanField(default=None, null=True)
|
|
@ -0,0 +1,56 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
from .models import *
|
||||||
|
|
||||||
|
|
||||||
|
class StudentSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Student
|
||||||
|
fields = '__all__'
|
||||||
|
# exclude = ['id']
|
||||||
|
|
||||||
|
|
||||||
|
class PlacementSerializer(serializers.ModelSerializer):
|
||||||
|
company_details = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_company_details(self, obj):
|
||||||
|
data = {
|
||||||
|
"id": obj.company.id,
|
||||||
|
"name": obj.company.name,
|
||||||
|
"address": obj.company.address,
|
||||||
|
"companyType": obj.company.companyType,
|
||||||
|
"website": obj.company.website,
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Placement
|
||||||
|
exclude=[COMPANY]
|
||||||
|
depth = 1
|
||||||
|
|
||||||
|
|
||||||
|
class PlacementApplicationSerializer(serializers.ModelSerializer):
|
||||||
|
application_status = serializers.SerializerMethodField()
|
||||||
|
company_details = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
|
||||||
|
def get_application_status(self, obj):
|
||||||
|
if obj.status is None:
|
||||||
|
return obj.placement.status
|
||||||
|
else:
|
||||||
|
return obj.status
|
||||||
|
|
||||||
|
|
||||||
|
def get_company_details(self, obj):
|
||||||
|
data = {
|
||||||
|
"id": obj.placement.company.id,
|
||||||
|
"name": obj.placement.company.name,
|
||||||
|
"address": obj.placement.company.address,
|
||||||
|
"companyType": obj.placement.company.companyType,
|
||||||
|
"website": obj.placement.company.website,
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = PlacementApplication
|
||||||
|
exclude = ['status', 'student']
|
|
@ -0,0 +1,12 @@
|
||||||
|
from django.urls import path, include
|
||||||
|
from . import studentViews
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('login/', studentViews.login, name="Login"),
|
||||||
|
path('profile/', studentViews.studentProfile, name="Student Profile"),
|
||||||
|
path('getDashboard/', studentViews.getDashboard, name="Dashboard"),
|
||||||
|
path("addResume/", studentViews.addResume, name="Upload Resume"),
|
||||||
|
path("deleteResume/", studentViews.deleteResume, name="Upload Resume"),
|
||||||
|
path("submitApplication/", studentViews.submitApplication, name="Submit Application"),
|
||||||
|
]
|
|
@ -0,0 +1,190 @@
|
||||||
|
import logging
|
||||||
|
from os import path, remove
|
||||||
|
|
||||||
|
from rest_framework.decorators import api_view
|
||||||
|
|
||||||
|
from .serializers import *
|
||||||
|
from .utils import *
|
||||||
|
|
||||||
|
logger = logging.getLogger('db')
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@isAuthorized(allowed_users='*')
|
||||||
|
def login(request, id, email, user_type):
|
||||||
|
try:
|
||||||
|
return Response({'action': "Login", 'message': "Verified", "user_type": user_type},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
except:
|
||||||
|
return Response({'action': "Login", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['GET'])
|
||||||
|
@isAuthorized(allowed_users=[STUDENT])
|
||||||
|
def studentProfile(request, id, email, user_type):
|
||||||
|
try:
|
||||||
|
studentDetails = get_object_or_404(Student, id=id)
|
||||||
|
|
||||||
|
data = StudentSerializer(studentDetails).data
|
||||||
|
return Response({'action': "Student Profile", 'message': "Details Found", "details": data},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
except:
|
||||||
|
return Response({'action': "Student Profile", 'message': "Error Occurred {0}".format(str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@isAuthorized(allowed_users=[STUDENT])
|
||||||
|
def addResume(request, id, email, user_type):
|
||||||
|
destination_path = ""
|
||||||
|
try:
|
||||||
|
student = get_object_or_404(Student, id=id)
|
||||||
|
prefix = generateRandomString()
|
||||||
|
files = request.FILES
|
||||||
|
file_name = prefix + "_" + files['file'].name
|
||||||
|
print(file_name)
|
||||||
|
student.resumes.append(file_name)
|
||||||
|
|
||||||
|
file = files['file']
|
||||||
|
destination_path = STORAGE_DESTINATION + str(file_name)
|
||||||
|
if path.exists(destination_path):
|
||||||
|
remove(destination_path)
|
||||||
|
|
||||||
|
with open(destination_path, 'wb+') as destination:
|
||||||
|
for chunk in file.chunks():
|
||||||
|
destination.write(chunk)
|
||||||
|
|
||||||
|
student.save()
|
||||||
|
return Response({'action': "Upload Resume", 'message': "Resume Added"},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
except Http404:
|
||||||
|
return Response({'action': "Upload Resume", 'message': 'Student Not Found'},
|
||||||
|
status=status.HTTP_404_NOT_FOUND)
|
||||||
|
except:
|
||||||
|
if path.exists(destination_path):
|
||||||
|
logger.error("Upload Resume: Error in Saving Resume")
|
||||||
|
remove(destination_path)
|
||||||
|
else:
|
||||||
|
logger.warning("Upload Resume: " + str(sys.exc_info()))
|
||||||
|
return Response({'action': "Upload Resume", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['GET'])
|
||||||
|
@isAuthorized(allowed_users=[STUDENT])
|
||||||
|
def getDashboard(request, id, email, user_type):
|
||||||
|
try:
|
||||||
|
studentDetails = get_object_or_404(Student, id=id)
|
||||||
|
|
||||||
|
placements = Placement.objects.filter(allowed_batch__contains=[studentDetails.batch],
|
||||||
|
allowed_branch__contains=[studentDetails.branch],
|
||||||
|
status=STATUS_ACCEPTING_APPLICATIONS)
|
||||||
|
placementsdata = PlacementSerializer(placements, many=True).data
|
||||||
|
|
||||||
|
placementApplications = PlacementApplication.objects.filter(student_id=id)
|
||||||
|
placementApplications = PlacementApplicationSerializer(placementApplications, many=True).data
|
||||||
|
|
||||||
|
return Response(
|
||||||
|
{'action': "Placement and Internships", 'message': "Data Found", "placements": placementsdata,
|
||||||
|
'placementApplication': placementApplications},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
except Http404:
|
||||||
|
return Response({'action': "Placements and Internships", 'message': 'Student Not Found'},
|
||||||
|
status=status.HTTP_404_NOT_FOUND)
|
||||||
|
except:
|
||||||
|
logger.warning("Placements and Internships: " + str(sys.exc_info()))
|
||||||
|
return Response({'action': "Placements and Internships", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@isAuthorized(allowed_users=[STUDENT])
|
||||||
|
@precheck(required_data=[RESUME_FILE_NAME])
|
||||||
|
def deleteResume(request, id, email, user_type):
|
||||||
|
try:
|
||||||
|
student = get_object_or_404(Student, id=id)
|
||||||
|
file_name = request.data[RESUME_FILE_NAME]
|
||||||
|
destination_path = STORAGE_DESTINATION + str(file_name)
|
||||||
|
if path.exists(destination_path):
|
||||||
|
remove(destination_path)
|
||||||
|
student.resumes.remove(file_name)
|
||||||
|
student.save()
|
||||||
|
return Response({'action': "Delete Resume", 'message': "Resume Deleted"},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError("File Not Found")
|
||||||
|
except Http404:
|
||||||
|
return Response({'action': "Delete Resume", 'message': 'Student Not Found'},
|
||||||
|
status=status.HTTP_404_NOT_FOUND)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
return Response({'action': "Delete Resume", 'message': str(e)},
|
||||||
|
status=status.HTTP_404_NOT_FOUND)
|
||||||
|
except:
|
||||||
|
logger.warning("Delete Resume: " + str(sys.exc_info()))
|
||||||
|
return Response({'action': "Delete Resume", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@isAuthorized(allowed_users=[STUDENT])
|
||||||
|
@precheck(required_data=[APPLICATION_OPENING_TYPE, APPLICATION_OPENING_ID, RESUME_FILE_NAME,
|
||||||
|
APPLICATION_ADDITIONAL_INFO])
|
||||||
|
def submitApplication(request, id, email, user_type):
|
||||||
|
try:
|
||||||
|
data = request.data
|
||||||
|
student = get_object_or_404(Student, id=id)
|
||||||
|
|
||||||
|
if data[APPLICATION_OPENING_TYPE] == PLACEMENT:
|
||||||
|
if not len(PlacementApplication.objects.filter(
|
||||||
|
student_id=id, placement_id=data[APPLICATION_OPENING_ID])):
|
||||||
|
application = PlacementApplication()
|
||||||
|
opening = get_object_or_404(Placement, id=data[APPLICATION_OPENING_ID],
|
||||||
|
status=STATUS_ACCEPTING_APPLICATIONS)
|
||||||
|
cond_stat, cond_msg = PlacementApplicationConditions(student, opening)
|
||||||
|
print(cond_stat, cond_msg)
|
||||||
|
if not cond_stat:
|
||||||
|
raise PermissionError(cond_msg)
|
||||||
|
application.placement = opening
|
||||||
|
else:
|
||||||
|
raise PermissionError("Application is already Submitted")
|
||||||
|
else:
|
||||||
|
raise ValueError(APPLICATION_OPENING_TYPE + " is Invalid")
|
||||||
|
|
||||||
|
if data[RESUME_FILE_NAME] in student.resumes:
|
||||||
|
application.resume = data[RESUME_FILE_NAME]
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError(RESUME_FILE_NAME + " Not Found")
|
||||||
|
|
||||||
|
application.student = student
|
||||||
|
application.id = generateRandomString()
|
||||||
|
for i in opening.additional_info:
|
||||||
|
if i not in data[APPLICATION_ADDITIONAL_INFO]:
|
||||||
|
print(i)
|
||||||
|
raise AttributeError(i + " not found in Additional Info")
|
||||||
|
|
||||||
|
application.additional_info = data[APPLICATION_ADDITIONAL_INFO]
|
||||||
|
if not sendApplicationEmail(email, student.name, opening.company.name, data[APPLICATION_OPENING_TYPE],
|
||||||
|
data[APPLICATION_ADDITIONAL_INFO]):
|
||||||
|
logger.error("Submit Application: Unable to Send Email")
|
||||||
|
# raise RuntimeError("Unable to Send Email")
|
||||||
|
|
||||||
|
application.save()
|
||||||
|
return Response({'action': "Submit Application", 'message': "Application Submitted"},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
except PermissionError as e:
|
||||||
|
return Response({'action': "Submit Application", 'message': str(e)},
|
||||||
|
status=status.HTTP_403_FORBIDDEN)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
return Response({'action': "Submit Application", 'message': str(e)},
|
||||||
|
status=status.HTTP_404_NOT_FOUND)
|
||||||
|
except:
|
||||||
|
logger.warning("Submit Application: " + str(sys.exc_info()))
|
||||||
|
return Response({'action': "Submit Application", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,10 @@
|
||||||
|
from django.urls import path, include
|
||||||
|
from . import studentViews, studentUrls, companyUrls, adminUrls
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('login/', studentViews.login, name="Login"),
|
||||||
|
path('student/', include(studentUrls)),
|
||||||
|
path('company/', include(companyUrls)),
|
||||||
|
path('admin/', include(adminUrls)),
|
||||||
|
|
||||||
|
]
|
|
@ -0,0 +1,197 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import sys
|
||||||
|
from os import path, remove
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
from django.http import Http404
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.utils.html import strip_tags
|
||||||
|
from google.auth.transport import requests
|
||||||
|
from google.oauth2 import id_token
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from .models import *
|
||||||
|
|
||||||
|
logger = logging.getLogger('db')
|
||||||
|
|
||||||
|
|
||||||
|
def precheck(required_data=None):
|
||||||
|
if required_data is None:
|
||||||
|
required_data = []
|
||||||
|
|
||||||
|
def decorator(view_func):
|
||||||
|
def wrapper_func(request, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
request_data = None
|
||||||
|
if request.method == 'GET':
|
||||||
|
request_data = request.GET
|
||||||
|
elif request.method == 'POST':
|
||||||
|
request_data = request.data
|
||||||
|
if not len(request_data):
|
||||||
|
request_data = request.POST
|
||||||
|
if len(request_data):
|
||||||
|
for i in required_data:
|
||||||
|
if i not in request_data:
|
||||||
|
return Response({'action': "Pre check", 'message': str(i) + " Not Found"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
else:
|
||||||
|
return Response({'action': "Pre check", 'message': "Message Data not Found"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
except:
|
||||||
|
return Response({'action': "Pre check", 'message': "Error Occurred " + str(sys.exc_info())},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
return wrapper_func
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def isAuthorized(allowed_users=None):
|
||||||
|
if allowed_users is None:
|
||||||
|
allowed_users = []
|
||||||
|
|
||||||
|
def decorator(view_func):
|
||||||
|
def wrapper_func(request, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
headers = request.META
|
||||||
|
if 'HTTP_AUTHORIZATION' in headers:
|
||||||
|
token_id = headers['HTTP_AUTHORIZATION'][7:]
|
||||||
|
idinfo = id_token.verify_oauth2_token(token_id, requests.Request(), CLIENT_ID)
|
||||||
|
email = idinfo[EMAIL]
|
||||||
|
print(email)
|
||||||
|
user = get_object_or_404(User, email=email)
|
||||||
|
if user:
|
||||||
|
|
||||||
|
if len(set(user.user_type).intersection(set(allowed_users))) or allowed_users == '*':
|
||||||
|
return view_func(request, user.id, user.email, user.user_type, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
raise PermissionError("Access Denied. You are not allowed to use this service")
|
||||||
|
else:
|
||||||
|
raise PermissionError("Authorization Header Not Found")
|
||||||
|
|
||||||
|
except PermissionError as e:
|
||||||
|
print(e)
|
||||||
|
return Response({'action': "Is Authorized?", 'message': str(e)},
|
||||||
|
status=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
except Http404:
|
||||||
|
print('http404')
|
||||||
|
return Response({'action': "Is Authorized?", 'message': "User Not Found. Contact CDC for more details"},
|
||||||
|
status=status.HTTP_404_NOT_FOUND)
|
||||||
|
except ValueError as e:
|
||||||
|
logger.warning("Problem with Google Oauth2.0 " + str(e))
|
||||||
|
return Response({'action': "Is Authorized?", 'message': str(e)},
|
||||||
|
status=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
except:
|
||||||
|
return Response({'action': "Is Authorized?", 'message': "Error Occurred {0}".format(
|
||||||
|
str(sys.exc_info()[1]))},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
return wrapper_func
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def generateRandomString():
|
||||||
|
try:
|
||||||
|
N = 15
|
||||||
|
res = ''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
|
||||||
|
return res
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def sendApplicationEmail(email, name, company_name, applicaton_type, additional_info):
|
||||||
|
try:
|
||||||
|
subject = 'CDC - Application Submitted - ' + str(company_name)
|
||||||
|
data = {
|
||||||
|
"name": name,
|
||||||
|
"company_name": company_name,
|
||||||
|
"applicaton_type": applicaton_type,
|
||||||
|
"additional_info": additional_info
|
||||||
|
}
|
||||||
|
|
||||||
|
html_content = render_to_string('student_application_submited.html', data) # render with dynamic value
|
||||||
|
text_content = strip_tags(html_content)
|
||||||
|
|
||||||
|
email_from = settings.EMAIL_HOST_USER
|
||||||
|
recipient_list = [str(email), ]
|
||||||
|
|
||||||
|
msg = EmailMultiAlternatives(subject, text_content, email_from, recipient_list)
|
||||||
|
msg.attach_alternative(html_content, "text/html")
|
||||||
|
msg.send()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def saveFile(file, location):
|
||||||
|
prefix = generateRandomString()
|
||||||
|
file_name = prefix + "_" + file.name
|
||||||
|
|
||||||
|
if not path.isdir(location):
|
||||||
|
os.mkdir(location)
|
||||||
|
|
||||||
|
destination_path = STORAGE_DESTINATION_COMPANY_ATTACHMENTS + str(file_name)
|
||||||
|
if path.exists(destination_path):
|
||||||
|
remove(destination_path)
|
||||||
|
|
||||||
|
with open(destination_path, 'wb+') as destination:
|
||||||
|
for chunk in file.chunks():
|
||||||
|
destination.write(chunk)
|
||||||
|
|
||||||
|
return file_name
|
||||||
|
|
||||||
|
|
||||||
|
def sendEmail(email_to, subject, data, template):
|
||||||
|
try:
|
||||||
|
html_content = render_to_string(template, data) # render with dynamic value
|
||||||
|
text_content = strip_tags(html_content)
|
||||||
|
|
||||||
|
email_from = settings.EMAIL_HOST_USER
|
||||||
|
recipient_list = [str(email_to), ]
|
||||||
|
|
||||||
|
msg = EmailMultiAlternatives(subject, text_content, email_from, recipient_list)
|
||||||
|
msg.attach_alternative(html_content, "text/html")
|
||||||
|
msg.send()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
print(str(sys.exc_info()[1]))
|
||||||
|
return str(sys.exc_info()[1])
|
||||||
|
|
||||||
|
|
||||||
|
def PlacementApplicationConditions(student, placement):
|
||||||
|
try:
|
||||||
|
selected_companies = PlacementApplication.objects.filter(student=student, selected=True)
|
||||||
|
selected_companies_PSU = [i for i in selected_companies if i.placement.tier == 'psu']
|
||||||
|
PPO = PrePlacementOffer.objects.filter(internship_application__student=student, accepted=True)
|
||||||
|
|
||||||
|
if len(selected_companies) + len(PPO) >= 2:
|
||||||
|
raise PermissionError("Max Applications Reached for the Season")
|
||||||
|
|
||||||
|
if len(selected_companies_PSU) > 0:
|
||||||
|
raise PermissionError('Selected for PSU Can\'t apply anymore')
|
||||||
|
|
||||||
|
if placement.tier == 'psu':
|
||||||
|
return True, "Conditions Satisfied"
|
||||||
|
|
||||||
|
for i in selected_companies:
|
||||||
|
print(int(i.placement.tier) < int(placement.tier), int(i.placement.tier), int(placement.tier))
|
||||||
|
if int(i.placement.tier) < int(placement.tier):
|
||||||
|
return False, "Can't apply for this tier"
|
||||||
|
|
||||||
|
return True, "Conditions Satisfied"
|
||||||
|
|
||||||
|
except PermissionError as e:
|
||||||
|
return False, e
|
||||||
|
except:
|
||||||
|
print(sys.exc_info())
|
||||||
|
logger.warning("Utils - PlacementApplicationConditions: " + str(sys.exc_info()))
|
||||||
|
return False, "_"
|
|
@ -0,0 +1,191 @@
|
||||||
|
"""
|
||||||
|
Django settings for CDC_Backend project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 2.2.5.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/2.2/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/2.2/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# import django_heroku
|
||||||
|
|
||||||
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'e_i2g3z!y4+p3dwm%k9k=zmsot@aya-0$mmetgxz4mp#8_oy#*'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ['cdc-iitdh.herokuapp.com/', 'localhost', '192.168.29.199']
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'APIs',
|
||||||
|
'rest_framework',
|
||||||
|
'corsheaders',
|
||||||
|
'django_db_logger',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'corsheaders.middleware.CorsMiddleware',
|
||||||
|
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'CDC_Backend.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': ['templates'],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'CDC_Backend.wsgi.application'
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
# 'default': {
|
||||||
|
# 'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||||
|
# }
|
||||||
|
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||||
|
'NAME': 'cdc',
|
||||||
|
'USER': 'postgres',
|
||||||
|
'PASSWORD': 'root',
|
||||||
|
'HOST': 'localhost',
|
||||||
|
'PORT': '5432',
|
||||||
|
},
|
||||||
|
# 'default': {
|
||||||
|
# 'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||||
|
# 'NAME': 'd84i5cbjig5rrf',
|
||||||
|
# 'USER': 'hbkullcdjbxuwh',
|
||||||
|
# 'PASSWORD': '45d990da00e2cc96d7d4e2e5e308d4b07a387883f70c40e090a6252175cb634e',
|
||||||
|
# 'HOST': 'ec2-54-163-97-228.compute-1.amazonaws.com',
|
||||||
|
# 'PORT': '5432',
|
||||||
|
# }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/2.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Asia/Kolkata'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_L10N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/2.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = '/static/'
|
||||||
|
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
|
||||||
|
STATICFILES_DIR = (
|
||||||
|
os.path.join(BASE_DIR, 'static'),
|
||||||
|
)
|
||||||
|
|
||||||
|
CORS_ORIGIN_ALLOW_ALL = True
|
||||||
|
CORS_ORIGIN_WHITELIST = [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"http://127.0.0.1:3000",
|
||||||
|
"http://localhost:8000",
|
||||||
|
"http://127.0.0.1:8000"
|
||||||
|
]
|
||||||
|
|
||||||
|
# EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
|
||||||
|
EMAIL_FILE_PATH = './emails'
|
||||||
|
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||||
|
EMAIL_HOST = 'smtp.gmail.com'
|
||||||
|
EMAIL_USE_TLS = True
|
||||||
|
EMAIL_PORT = 587
|
||||||
|
EMAIL_HOST_USER = 'saisurya3127@gmail.com'#'email here'
|
||||||
|
EMAIL_HOST_PASSWORD = 'ehwkqmryyqjiifcz'#'password here'
|
||||||
|
|
||||||
|
LOGGING = {
|
||||||
|
'version': 1,
|
||||||
|
'disable_existing_loggers': False,
|
||||||
|
'formatters': {
|
||||||
|
'verbose': {
|
||||||
|
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
|
||||||
|
},
|
||||||
|
'simple': {
|
||||||
|
'format': '%(levelname)s %(asctime)s %(message)s'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'db_log': {
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'class': 'django_db_logger.db_log_handler.DatabaseLogHandler'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'loggers': {
|
||||||
|
'db': {
|
||||||
|
'handlers': ['db_log'],
|
||||||
|
'level': 'DEBUG'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# django_heroku.settings(locals())
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
path('api/', include('APIs.urls'))
|
||||||
|
]
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
WSGI config for CDC_Backend project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CDC_Backend.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
|
@ -0,0 +1,403 @@
|
||||||
|
# API References
|
||||||
|
1. [**Common APIs**](#common-apis)
|
||||||
|
1. [**api/login/**](#apilogin)
|
||||||
|
2[**Student APIs**](#student-portal-apis)
|
||||||
|
2. [**api/student/profile/**](#apistudentprofile)
|
||||||
|
3. [**api/student/getDashboard/**](#apistudentgetdashboard)
|
||||||
|
4. [**api/student/addResume/**](#apistudentaddresume)
|
||||||
|
5. [**api/student/deleteResume/**](#apistudentdeleteresume)
|
||||||
|
6. [**api/student/submitApplication/**](#apistudentsubmitapplication)
|
||||||
|
3[**Common Errors**](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Common APIs
|
||||||
|
|
||||||
|
## `api/login/`
|
||||||
|
|
||||||
|
This Api is used to Verify the user and find out the role he/she has
|
||||||
|
|
||||||
|
### How to Use?
|
||||||
|
|
||||||
|
Send a `POST` request to `api/login/`<br>
|
||||||
|
Request_Body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Headers <br>
|
||||||
|
> Authorization: "Bearer {tokenID}"
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Response is a Json with these fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "Login",
|
||||||
|
"message": "Verified",
|
||||||
|
"user_type": [
|
||||||
|
"student"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- action: Tells us about the message creator<Br>
|
||||||
|
- message: Tells us what happened with our Request.
|
||||||
|
- user_type: Tells us about the role the user possess. Can have these values
|
||||||
|
- student
|
||||||
|
- Admin
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
|
||||||
|
The possible responses for this api request are as follows
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages |
|
||||||
|
| ------------ | ----------------- |
|
||||||
|
| 200 OK | `Verified` |
|
||||||
|
|
||||||
|
You may see some different errors which can be seen [here](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Student Portal APIs
|
||||||
|
|
||||||
|
## `api/student/profile`
|
||||||
|
|
||||||
|
This Api is used to get the profile of the student.
|
||||||
|
|
||||||
|
### How to Use?
|
||||||
|
|
||||||
|
Send a `GET` request to `api/student/profile`<br>
|
||||||
|
Request_Body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Headers <br>
|
||||||
|
> Authorization: "Bearer {tokenID}"
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Response is a Json with these fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "Student Profile",
|
||||||
|
"message": "Details Found",
|
||||||
|
"details": {
|
||||||
|
"id": "fdgdb",
|
||||||
|
"roll_no": 190010036,
|
||||||
|
"name": "Gowtham Sai",
|
||||||
|
"batch": "THIRD",
|
||||||
|
"branch": "CSE",
|
||||||
|
"phone_number": 9390291911,
|
||||||
|
"resumes": [
|
||||||
|
"XB85F4RIGBF5VJN_Cv-Gowtham.pdf"
|
||||||
|
],
|
||||||
|
"cpi": "9.02"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- action: Tells us about the message creator<Br>
|
||||||
|
- message: Tells us what happened with our Request.
|
||||||
|
- details: Has the student data.
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
|
||||||
|
The possible responses for this api request are as follows
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages |
|
||||||
|
| --------------- | ------------------------ |
|
||||||
|
| 200 OK | `Details Found` |
|
||||||
|
| 400 BAD_REQUEST | `Error Occurred {error}` |
|
||||||
|
|
||||||
|
You may see some different errors which can be seen [here](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `api/student/getDashboard`
|
||||||
|
|
||||||
|
This Api is used to get all the placements applicable to the student.
|
||||||
|
|
||||||
|
### How to Use?
|
||||||
|
|
||||||
|
Send a `GET` request to `api/student/Dashboard`<br>
|
||||||
|
|
||||||
|
Request_Body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Headers <br>
|
||||||
|
> Authorization: "Bearer {tokenID}"
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Response is a Json with these fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "Placement and Internships",
|
||||||
|
"message": "Data Found",
|
||||||
|
"placements": [
|
||||||
|
{
|
||||||
|
"id": "fdgdb121",
|
||||||
|
"designation": "Software Developer",
|
||||||
|
"description": "nice job",
|
||||||
|
"start_date": "2021-06-17",
|
||||||
|
"city": "Mumbai",
|
||||||
|
"city_type": "Domestic",
|
||||||
|
"compensation": 1200000,
|
||||||
|
"compensation_details": "",
|
||||||
|
"allowed_batch": [
|
||||||
|
"THIRD",
|
||||||
|
"FOURTH"
|
||||||
|
],
|
||||||
|
"allowed_branch": [
|
||||||
|
"CSE",
|
||||||
|
"EE",
|
||||||
|
"ME"
|
||||||
|
],
|
||||||
|
"attachments": [],
|
||||||
|
"rounds": [
|
||||||
|
"Resume Shortlisting",
|
||||||
|
"Technical Test",
|
||||||
|
"Interview"
|
||||||
|
],
|
||||||
|
"additional_info": [
|
||||||
|
"school",
|
||||||
|
"place of study",
|
||||||
|
"language"
|
||||||
|
],
|
||||||
|
"status": "Resume Shortlisting",
|
||||||
|
"rounds_details": {
|
||||||
|
"Interview": "One -to-One interview",
|
||||||
|
"Technical Test": "Online Technical test which will be monitored remotely",
|
||||||
|
"Resume Shortlisting": "Resume will be seen"
|
||||||
|
},
|
||||||
|
"company_details": {
|
||||||
|
"id": "fdgdb",
|
||||||
|
"name": "Apple",
|
||||||
|
"address": "California",
|
||||||
|
"companyType": "Technology",
|
||||||
|
"website": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"placementApplication": [
|
||||||
|
{
|
||||||
|
"id": "dsdads",
|
||||||
|
"application_status": "Resume Shortlisting",
|
||||||
|
"resume": "XB85F4RIGBF5VJN_Cv-Gowtham.pdf",
|
||||||
|
"additional_info": {
|
||||||
|
"school": "Delhi Public School",
|
||||||
|
"language": "Telugu",
|
||||||
|
"place of study": "Visakhapatnam"
|
||||||
|
},
|
||||||
|
"selected": null,
|
||||||
|
"placement": "fdgdb121"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- action: Tells us about the message creator<Br>
|
||||||
|
- message: Tells us what happened with our Request.
|
||||||
|
- placements: Has the placements data.
|
||||||
|
- internships: Has the internships data.
|
||||||
|
- application_status: Can have many names
|
||||||
|
- Accepting Applications
|
||||||
|
- One of the Round Names
|
||||||
|
- Completed
|
||||||
|
- selected: Can take three Values
|
||||||
|
- null: Student is still in the Selection process
|
||||||
|
- true: Student is Selected
|
||||||
|
- false: Student is not selected
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
|
||||||
|
The possible responses for this api request are as follows
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages |
|
||||||
|
| --------------- | ------------------------ |
|
||||||
|
| 200 OK | `Resume Added` |
|
||||||
|
| 400 BAD_REQUEST | `Error Occurred {error}` |
|
||||||
|
|
||||||
|
You can see some common errors [here](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `api/student/addResume/`
|
||||||
|
|
||||||
|
This Api is used to add resumes by a student.
|
||||||
|
|
||||||
|
### How to Use?
|
||||||
|
|
||||||
|
Send a `POST` request to `api/student/addResume/`<br>
|
||||||
|
|
||||||
|
> Only users with `student` role can access this Api.
|
||||||
|
|
||||||
|
Request_Body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"file": "__FILE_OBJECT__"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Excepted to send Form Data
|
||||||
|
|
||||||
|
> Headers <br>
|
||||||
|
> Authorization: "Bearer {tokenID}"
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Response is a Json with these fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "Upload Resume",
|
||||||
|
"message": "Resume Added"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- action: Tells us about the message creator<Br>
|
||||||
|
- message: Tells us what happened with our Request.
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
|
||||||
|
The possible responses for this api request are as follows
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages |
|
||||||
|
| ------------ | ----------------- |
|
||||||
|
| 200 OK | `Resume Added` |
|
||||||
|
|
||||||
|
You can see some common errors [here](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `api/student/deleteResume/`
|
||||||
|
|
||||||
|
This Api is used to delete resumes added by a student.
|
||||||
|
|
||||||
|
### How to Use?
|
||||||
|
|
||||||
|
Send a `POST` request to `api/student/deleteResume/`<br>
|
||||||
|
|
||||||
|
> Only users with `student` role can access this Api.
|
||||||
|
|
||||||
|
Request_Body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"resume_file_name": "8ZJ44RIS9914SO4_Resume for Google STEP.pdf"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Response is a Json with these fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "Delete Resume",
|
||||||
|
"message": "Resume Deleted"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Headers <br>
|
||||||
|
> Authorization: "Bearer {tokenID}"
|
||||||
|
|
||||||
|
- action: Tells us about the message creator<Br>
|
||||||
|
- message: Tells us what happened with our Request.
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
|
||||||
|
The possible responses for this api request are as follows
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages |
|
||||||
|
| ------------- | ----------------- |
|
||||||
|
| 200 OK | `Resume Deleted` |
|
||||||
|
| 404 NOT FOUND | `File Not Found` |
|
||||||
|
|
||||||
|
You can see some common errors [here](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `api/student/submitApplication/`
|
||||||
|
|
||||||
|
This Api is used to submit application to Internships/Placements.
|
||||||
|
|
||||||
|
### How to Use?
|
||||||
|
|
||||||
|
Send a `POST` request to `api/student/submitApplication/`<br>
|
||||||
|
|
||||||
|
> Only users with `student` role can access this Api.
|
||||||
|
|
||||||
|
Request_Body:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"opening_type": "Placement",
|
||||||
|
"opening_id": "fgervsdgdsf",
|
||||||
|
"resume_file_name": "1FYE0PQZZ508HR6_Resume for Google STEP.pdf",
|
||||||
|
"additional_info": {
|
||||||
|
"school": "Narayana English Medium",
|
||||||
|
"place of study": "Vizag",
|
||||||
|
"language": "Telugu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Headers <br>
|
||||||
|
> Authorization: "Bearer {tokenID}"
|
||||||
|
|
||||||
|
- opening_type: Can be Placement/Internship
|
||||||
|
- opening_id: Opening Id unique to each opening.
|
||||||
|
- additional_info: This is the info which the Internship/Placement demands besides the normal user data which has to
|
||||||
|
asked and sent. These fields can be found in the Internship Details.
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Response is a Json with these fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "Submit Application",
|
||||||
|
"message": "Application Submitted"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- action: Tells us about the message creator<Br>
|
||||||
|
- message: Tells us what happened with our Request.
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
|
||||||
|
The possible responses for this api request are as follows
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages |
|
||||||
|
| ------------- | ---------------------------------- |
|
||||||
|
| 200 OK | `Application Submitted` |
|
||||||
|
| 403 FORBIDDEN | `Application is already Submitted` |
|
||||||
|
| 404 NOT FOUND | `RESUME_FILE_NAME Not Found` |
|
||||||
|
|
||||||
|
You can see some common errors [here](#common-errors)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `Common Errors`
|
||||||
|
|
||||||
|
Some common errors that you may see while accessing the Apis
|
||||||
|
|
||||||
|
| Status Codes | Possible Messages | Possible Reasons |
|
||||||
|
| ---------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||||
|
| 401 UNAUTHORIZED | `Authorization Header Not Found` | Check for the authorization header in you request and the prefix( Should use `Bearer`) used. |
|
||||||
|
| 401 UNAUTHORIZED | `Access Denied. You are not allowed to use this service` | Your may not have required access to those access those Apis. |
|
||||||
|
| 401 UNAUTHORIZED | `Token has wrong audience` | You may be using wrong credentials for Google OAuth2.0. |
|
||||||
|
| 404 NOT FOUND | `User Not Found. Contact CDC for more details` | You may not be a user at CDC, IIT Dharwad. Please contact us to get your user account |
|
||||||
|
| 400 BAD_REQUEST | `Error Occurred {error}` | Any random Error which can be seen in the {error} string. |
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"web": {
|
||||||
|
"client_id": "956830229554-290mirc16pdhd5j7ph7v7ukibo4t1qcp.apps.googleusercontent.com",
|
||||||
|
"project_id": "cdc-automation",
|
||||||
|
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||||
|
"token_uri": "https://oauth2.googleapis.com/token",
|
||||||
|
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||||
|
"client_secret": "ZzvcweJylL1IDLUnYOi1ws2W",
|
||||||
|
"redirect_uris": ["https://www.getpostman.com/oauth2/callback"],
|
||||||
|
"javascript_origins": ["http://localhost:3000"]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CDC_Backend.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,113 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<meta name="x-apple-disable-message-reformatting">
|
||||||
|
<title></title>
|
||||||
|
<!--[if mso]>
|
||||||
|
<noscript>
|
||||||
|
<xml>
|
||||||
|
<o:OfficeDocumentSettings>
|
||||||
|
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||||
|
</o:OfficeDocumentSettings>
|
||||||
|
</xml>
|
||||||
|
</noscript>
|
||||||
|
<![endif]-->
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
table, td, div, h1, p {
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:0;padding:0;">
|
||||||
|
<table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding:0;">
|
||||||
|
<table role="presentation"
|
||||||
|
style="width:602px;border-collapse:collapse;border:1px solid #334878;border-spacing:0;text-align:left;">
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding:40px 0 30px 0;background:#334878;">
|
||||||
|
<img src="./image.png" alt="" width="200" style="height:auto;display:block;"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding:36px 30px 42px 30px;">
|
||||||
|
<table role="presentation"
|
||||||
|
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
|
||||||
|
<tr>
|
||||||
|
<td style="padding:0 0 36px 0;color:#153643;">
|
||||||
|
<h1 style="font-size:24px;margin:0 0 20px 0;font-family: 'Roboto', sans-serif;
|
||||||
|
">Hello there, {{ name }}</h1>
|
||||||
|
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
|
||||||
|
We have received your application for a <b>{{ applicaton_type }}</b> offer at <b>
|
||||||
|
{{ company_name }}</b>
|
||||||
|
. We received these additional details<br>
|
||||||
|
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family:
|
||||||
|
'Roboto', sans-serif;text-align: center">
|
||||||
|
|
||||||
|
<table style="border:solid 1px; margin: auto; text-align: center;width: 80%;
|
||||||
|
border-radius:15px; background-color: #e0e3ee">
|
||||||
|
|
||||||
|
{% for i,j in additional_info.items %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td style="padding:8px 10px;color:#153643; ">{{ i }}:</td>
|
||||||
|
<td style="padding:8px 10px;color:#153643;">{{ j }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</p>
|
||||||
|
<p style="margin:0 0 12px 0;font-size:16px;line-height:24px;font-family: 'Roboto', sans-serif;">
|
||||||
|
We will keep you informed with the updates. If you have any queries, please
|
||||||
|
feel to
|
||||||
|
write to
|
||||||
|
<nobr><u>cdc.support@iitdh.ac.in</u></nobr>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding:0;">
|
||||||
|
<table role="presentation"
|
||||||
|
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;">
|
||||||
|
<tr>
|
||||||
|
<td style="width:260px;padding:0;vertical-align:top;color:#334878;">
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding:30px;background:#334878;">
|
||||||
|
<table role="presentation"
|
||||||
|
style="width:100%;border-collapse:collapse;border:0;border-spacing:0;font-size:9px;font-family: 'Roboto', sans-serif;">
|
||||||
|
<tr>
|
||||||
|
<td style="padding:0;width:50%;" align="left">
|
||||||
|
<p style="margin:0;font-size:14px;line-height:16px;font-family: 'Roboto', sans-serif;color:#ffffff;">
|
||||||
|
® CDC,IIT Dharwad,2021<br/>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
40
README.md
40
README.md
|
@ -1 +1,39 @@
|
||||||
# cdc-placement-website-backend
|
# CDC - Backend
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
1. Download the Repository to your local machine <br>
|
||||||
|
2. Create a Virtual Environment in the [CDC_Backend](./) folder with this command below <br>
|
||||||
|
`python -m venv venv`
|
||||||
|
3. Activate the environment with this command <br>
|
||||||
|
`.\venv\Scripts\activate`
|
||||||
|
4. Install the dependencies <br>
|
||||||
|
`pip install -r requirements.txt `
|
||||||
|
5. Ensure that you have the PostgreSQL installed on your machine and is running on PORT **5432** <br>
|
||||||
|
6. Make sure to give the correct database credentials in [settings.py](./CDC_Backend/CDC_Backend/settings.py)
|
||||||
|
|
||||||
|
### Running the Application
|
||||||
|
|
||||||
|
1. Activate the environment with this command. <br>
|
||||||
|
`.\venv\Scripts\activate`
|
||||||
|
2. Start the application by running this command (_Run the command where [manage.py](./CDC_Backend/manage.py) is
|
||||||
|
located_) <br>
|
||||||
|
` python manage.py runserver`
|
||||||
|
|
||||||
|
### Accessing the Admin Panel
|
||||||
|
|
||||||
|
1. You can access the admin panel by running the server and opening <http://localhost:8000/admin>
|
||||||
|
2. Run `python manage.py createsuperuser` to create a user to access the admin panel.
|
||||||
|
3. Set up the Username and Password
|
||||||
|
4. You can log in and change the database values anytime.
|
||||||
|
|
||||||
|
### Deploying
|
||||||
|
|
||||||
|
1. Add the hosted domain name in `ALLOWED_HOSTS` in [settings.py](./CDC_Backend/CDC_Backend/settings.py)
|
||||||
|
2. Update the `CORS_ORIGIN_WHITELIST` list and `CORS_ORIGIN_ALLOW_ALL` variable
|
||||||
|
|
||||||
|
### API Reference
|
||||||
|
|
||||||
|
Check [here](./CDC_Backend/README.md) for Api Reference
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
asgiref==3.4.1
|
||||||
|
astroid==2.7.1
|
||||||
|
cachetools==4.2.2
|
||||||
|
certifi==2021.5.30
|
||||||
|
chardet==4.0.0
|
||||||
|
colorama==0.4.4
|
||||||
|
dj-database-url==0.5.0
|
||||||
|
Django==3.2.6
|
||||||
|
django-cors-headers==3.8.0
|
||||||
|
django-db-logger==0.1.10
|
||||||
|
djangorestframework==3.12.4
|
||||||
|
google-auth==2.0.0
|
||||||
|
idna==3.2
|
||||||
|
isort==5.9.3
|
||||||
|
jsonfield==3.1.0
|
||||||
|
lazy-object-proxy==1.6.0
|
||||||
|
Markdown==3.3.4
|
||||||
|
mccabe==0.6.1
|
||||||
|
psycopg2==2.9.1
|
||||||
|
pyasn1==0.4.8
|
||||||
|
pyasn1-modules==0.2.8
|
||||||
|
pylint==2.9.6
|
||||||
|
pytz==2021.1
|
||||||
|
requests==2.26.0
|
||||||
|
rsa==4.7.2
|
||||||
|
six==1.16.0
|
||||||
|
sqlparse==0.4.1
|
||||||
|
toml==0.10.2
|
||||||
|
urllib3==1.26.6
|
||||||
|
whitenoise==5.3.0
|
||||||
|
wrapt==1.12.1
|
Loading…
Reference in New Issue