├── .gitignore └── backend ├── backend ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── job ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── serializers.py ├── tests.py ├── urls.py └── views.py └── manage.py /.gitignore: -------------------------------------------------------------------------------- 1 | myenv/ 2 | backend/db.sqlite3 3 | backend/backend/.env 4 | backend/static/ -------------------------------------------------------------------------------- /backend/backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghulamabbas2/jobbee-django-nextjs/686687e4262fe913dcc93a716891cae145091fb7/backend/backend/__init__.py -------------------------------------------------------------------------------- /backend/backend/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for backend project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /backend/backend/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for backend project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.0.2. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | import dotenv 16 | 17 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 18 | BASE_DIR = Path(__file__).resolve().parent.parent 19 | 20 | dotenv.read_dotenv() 21 | 22 | # Quick-start development settings - unsuitable for production 23 | # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ 24 | 25 | # SECURITY WARNING: keep the secret key used in production secret! 26 | SECRET_KEY = os.environ.get('SECRET_KEY') 27 | 28 | # SECURITY WARNING: don't run with debug turned on in production! 29 | DEBUG = os.environ.get('DEBUG') == 'True' 30 | 31 | ALLOWED_HOSTS = [] 32 | 33 | 34 | # Application definition 35 | 36 | INSTALLED_APPS = [ 37 | 'django.contrib.admin', 38 | 'django.contrib.auth', 39 | 'django.contrib.contenttypes', 40 | 'django.contrib.sessions', 41 | 'django.contrib.messages', 42 | 'django.contrib.staticfiles', 43 | 44 | 'rest_framework', 45 | 'corsheaders', 46 | # 'storages' 47 | 'django.contrib.gis', 48 | 'django_filters', 49 | 50 | 'job.apps.JobConfig' 51 | ] 52 | 53 | MIDDLEWARE = [ 54 | 'django.middleware.security.SecurityMiddleware', 55 | 'django.contrib.sessions.middleware.SessionMiddleware', 56 | 'django.middleware.common.CommonMiddleware', 57 | 'django.middleware.csrf.CsrfViewMiddleware', 58 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 59 | 'django.contrib.messages.middleware.MessageMiddleware', 60 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 61 | ] 62 | 63 | ROOT_URLCONF = 'backend.urls' 64 | 65 | TEMPLATES = [ 66 | { 67 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 68 | 'DIRS': [], 69 | 'APP_DIRS': True, 70 | 'OPTIONS': { 71 | 'context_processors': [ 72 | 'django.template.context_processors.debug', 73 | 'django.template.context_processors.request', 74 | 'django.contrib.auth.context_processors.auth', 75 | 'django.contrib.messages.context_processors.messages', 76 | ], 77 | }, 78 | }, 79 | ] 80 | 81 | WSGI_APPLICATION = 'backend.wsgi.application' 82 | 83 | 84 | # Database 85 | # https://docs.djangoproject.com/en/4.0/ref/settings/#databases 86 | 87 | DATABASES = { 88 | 'default': { 89 | 'ENGINE': 'django.contrib.gis.db.backends.postgis', 90 | 'NAME': os.environ.get('DATABASE_NAME'), 91 | 'USER': os.environ.get('DATABASE_USER'), 92 | 'PASSWORD': os.environ.get('DATABASE_PASSWORD'), 93 | 'HOST': os.environ.get('DATABASE_HOST'), 94 | 'PORT': os.environ.get('DATABASE_PORT') 95 | } 96 | } 97 | 98 | 99 | # Password validation 100 | # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators 101 | 102 | AUTH_PASSWORD_VALIDATORS = [ 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 105 | }, 106 | { 107 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 108 | }, 109 | { 110 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 111 | }, 112 | { 113 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 114 | }, 115 | ] 116 | 117 | 118 | # Internationalization 119 | # https://docs.djangoproject.com/en/4.0/topics/i18n/ 120 | 121 | LANGUAGE_CODE = 'en-us' 122 | 123 | TIME_ZONE = 'UTC' 124 | 125 | USE_I18N = True 126 | 127 | USE_TZ = True 128 | 129 | 130 | # Static files (CSS, JavaScript, Images) 131 | # https://docs.djangoproject.com/en/4.0/howto/static-files/ 132 | 133 | 134 | STATIC_URL = 'static/' 135 | 136 | # Default primary key field type 137 | # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field 138 | 139 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 140 | 141 | GDAL_LIBRARY_PATH = os.environ.get('GDAL_LIBRARY_PATH') 142 | GEOS_LIBRARY_PATH = os.environ.get('GEOS_LIBRARY_PATH') -------------------------------------------------------------------------------- /backend/backend/urls.py: -------------------------------------------------------------------------------- 1 | """backend URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.urls import include 17 | from django.contrib import admin 18 | from django.urls import path 19 | 20 | urlpatterns = [ 21 | path('admin/', admin.site.urls), 22 | path('api/', include('job.urls')) 23 | ] 24 | -------------------------------------------------------------------------------- /backend/backend/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for backend project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /backend/job/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghulamabbas2/jobbee-django-nextjs/686687e4262fe913dcc93a716891cae145091fb7/backend/job/__init__.py -------------------------------------------------------------------------------- /backend/job/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Job 3 | 4 | # Register your models here. 5 | admin.site.register(Job) -------------------------------------------------------------------------------- /backend/job/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class JobConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'job' 7 | -------------------------------------------------------------------------------- /backend/job/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.2 on 2022-02-20 18:32 2 | 3 | from django.conf import settings 4 | import django.contrib.gis.db.models.fields 5 | import django.contrib.gis.geos.point 6 | import django.core.validators 7 | from django.db import migrations, models 8 | import django.db.models.deletion 9 | import job.models 10 | 11 | 12 | class Migration(migrations.Migration): 13 | 14 | initial = True 15 | 16 | dependencies = [ 17 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 18 | ] 19 | 20 | operations = [ 21 | migrations.CreateModel( 22 | name='Job', 23 | fields=[ 24 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 25 | ('title', models.CharField(max_length=200, null=True)), 26 | ('description', models.TextField(null=True)), 27 | ('email', models.EmailField(max_length=254, null=True)), 28 | ('address', models.CharField(max_length=100, null=True)), 29 | ('jobType', models.CharField(choices=[('Permanent', 'Permanent'), ('Temporary', 'Temporary'), ('Intership', 'Intership')], default='Permanent', max_length=10)), 30 | ('education', models.CharField(choices=[('Bachelors', 'Bachelors'), ('Masters', 'Masters'), ('Phd', 'Phd')], default='Bachelors', max_length=10)), 31 | ('industry', models.CharField(choices=[('Business', 'Business'), ('Information Technology', 'It'), ('Banking', 'Banking'), ('Education/Training', 'Education'), ('Telecommunication', 'Telecommunication'), ('Others', 'Others')], default='Business', max_length=30)), 32 | ('experience', models.CharField(choices=[('No Experience', 'No Experience'), ('1 Years', 'One Year'), ('2 Years', 'Two Year'), ('3 Years above', 'Three Year Plus')], default='No Experience', max_length=20)), 33 | ('salary', models.IntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(1000000)])), 34 | ('positions', models.IntegerField(default=1)), 35 | ('company', models.CharField(max_length=100, null=True)), 36 | ('point', django.contrib.gis.db.models.fields.PointField(default=django.contrib.gis.geos.point.Point(0.0, 0.0), srid=4326)), 37 | ('lastDate', models.DateTimeField(default=job.models.return_date_time)), 38 | ('createdAt', models.DateTimeField(auto_now_add=True)), 39 | ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), 40 | ], 41 | ), 42 | ] 43 | -------------------------------------------------------------------------------- /backend/job/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghulamabbas2/jobbee-django-nextjs/686687e4262fe913dcc93a716891cae145091fb7/backend/job/migrations/__init__.py -------------------------------------------------------------------------------- /backend/job/models.py: -------------------------------------------------------------------------------- 1 | from datetime import * 2 | from django.db import models 3 | from django.contrib.auth.models import User 4 | 5 | import geocoder 6 | import os 7 | 8 | from django.contrib.gis.db import models as gismodels 9 | from django.contrib.gis.geos import Point 10 | 11 | from django.core.validators import MinValueValidator, MaxValueValidator 12 | 13 | # Create your models here. 14 | 15 | class JobType(models.TextChoices): 16 | Permanent = 'Permanent' 17 | Temporary = 'Temporary' 18 | Intership = 'Intership' 19 | 20 | class Education(models.TextChoices): 21 | Bachelors = 'Bachelors' 22 | Masters = 'Masters' 23 | Phd = 'Phd' 24 | 25 | class Industry(models.TextChoices): 26 | Business = 'Business' 27 | IT = 'Information Technology' 28 | Banking = 'Banking' 29 | Education = 'Education/Training' 30 | Telecommunication = 'Telecommunication' 31 | Others = 'Others' 32 | 33 | class Experience(models.TextChoices): 34 | NO_EXPERIENCE = 'No Experience' 35 | ONE_YEAR = '1 Years' 36 | TWO_YEAR = '2 Years' 37 | THREE_YEAR_PLUS = '3 Years above' 38 | 39 | def return_date_time(): 40 | now = datetime.now() 41 | return now + timedelta(days=10) 42 | 43 | class Job(models.Model): 44 | title = models.CharField(max_length=200, null=True) 45 | description = models.TextField(null=True) 46 | email = models.EmailField(null=True) 47 | address = models.CharField(max_length=100, null=True) 48 | jobType = models.CharField( 49 | max_length=10, 50 | choices=JobType.choices, 51 | default=JobType.Permanent 52 | ) 53 | education = models.CharField( 54 | max_length=10, 55 | choices=Education.choices, 56 | default=Education.Bachelors 57 | ) 58 | industry = models.CharField( 59 | max_length=30, 60 | choices=Industry.choices, 61 | default=Industry.Business 62 | ) 63 | experience = models.CharField( 64 | max_length=20, 65 | choices=Experience.choices, 66 | default=Experience.NO_EXPERIENCE 67 | ) 68 | salary = models.IntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(1000000)]) 69 | positions = models.IntegerField(default=1) 70 | company = models.CharField(max_length=100, null=True) 71 | point = gismodels.PointField(default=Point(0.0, 0.0)) 72 | lastDate = models.DateTimeField(default=return_date_time) 73 | user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) 74 | createdAt = models.DateTimeField(auto_now_add=True) 75 | 76 | def save(self, *args, **kwargs): 77 | g = geocoder.mapquest(self.address, key=os.environ.get('GEOCODER_API')) 78 | 79 | print(g) 80 | 81 | lng = g.lng 82 | lat = g.lat 83 | 84 | self.point = Point(lng, lat) 85 | super(Job, self).save(*args, **kwargs) -------------------------------------------------------------------------------- /backend/job/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from .models import Job 3 | 4 | class JobSerializer(serializers.ModelSerializer): 5 | class Meta: 6 | model = Job 7 | fields ='__all__' -------------------------------------------------------------------------------- /backend/job/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/job/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | urlpatterns = [ 5 | path('jobs/', views.getAllJobs, name='jobs'), 6 | path('jobs/new/', views.newJob, name='new_job'), 7 | path('jobs//', views.getJob, name='job'), 8 | path('jobs//update/', views.updateJob, name='update_job'), 9 | path('jobs//delete/', views.deleteJob, name='delete_job'), 10 | path('stats//', views.getTopicStats, name='get_topic_stats') 11 | ] -------------------------------------------------------------------------------- /backend/job/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from rest_framework.decorators import api_view 3 | from rest_framework.response import Response 4 | from rest_framework import status 5 | from django.db.models import Avg, Min, Max, Count 6 | 7 | from .serializers import JobSerializer 8 | from .models import Job 9 | 10 | from django.shortcuts import get_object_or_404 11 | 12 | # Create your views here. 13 | 14 | @api_view(['GET']) 15 | def getAllJobs(request): 16 | 17 | jobs = Job.objects.all() 18 | 19 | serializer = JobSerializer(jobs, many=True) 20 | return Response(serializer.data) 21 | 22 | 23 | @api_view(['GET']) 24 | def getJob(request, pk): 25 | job = get_object_or_404(Job, id=pk) 26 | 27 | serializer = JobSerializer(job, many=False) 28 | 29 | return Response(serializer.data) 30 | 31 | 32 | @api_view(['POST']) 33 | def newJob(request): 34 | data = request.data 35 | 36 | job = Job.objects.create(**data) 37 | 38 | serializer = JobSerializer(job, many=False) 39 | return Response(serializer.data) 40 | 41 | 42 | @api_view(['PUT']) 43 | def updateJob(request, pk): 44 | job = get_object_or_404(Job, id=pk) 45 | 46 | job.title = request.data['title'] 47 | job.description = request.data['description'] 48 | job.email = request.data['email'] 49 | job.address = request.data['address'] 50 | job.jobType = request.data['jobType'] 51 | job.education = request.data['education'] 52 | job.industry = request.data['industry'] 53 | job.experience = request.data['experience'] 54 | job.salary = request.data['salary'] 55 | job.positions = request.data['positions'] 56 | job.company = request.data['company'] 57 | 58 | job.save() 59 | 60 | serializer = JobSerializer(job, many=False) 61 | 62 | return Response(serializer.data) 63 | 64 | 65 | @api_view(['DELETE']) 66 | def deleteJob(request, pk): 67 | job = get_object_or_404(Job, id=pk) 68 | 69 | job.delete() 70 | 71 | return Response({ 'message': 'Job is Deleted.' }, status=status.HTTP_200_OK) 72 | 73 | 74 | @api_view(['GET']) 75 | def getTopicStats(request, topic): 76 | 77 | args = { 'title__icontains': topic } 78 | jobs = Job.objects.filter(**args) 79 | 80 | if len(jobs) == 0: 81 | return Response({ 'message': 'Not stats found for {topic}'.format(topic=topic) }) 82 | 83 | 84 | stats = jobs.aggregate( 85 | total_jobs = Count('title'), 86 | avg_positions = Avg('positions'), 87 | avg_salary = Avg('salary'), 88 | min_salary = Min('salary'), 89 | max_salary = Max('salary') 90 | ) 91 | 92 | return Response(stats) -------------------------------------------------------------------------------- /backend/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | --------------------------------------------------------------------------------