├── .gitignore
├── Deployment
├── apache-site.conf
└── ems_gunicorn_service
├── Dockerfile
├── Dockerrun.aws.json
├── READEME.md
├── _config.yml
├── app.json
├── employee
├── __init__.py
├── admin.py
├── api_urls.py
├── apps.py
├── forms.py
├── middlewares.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20180415_0554.py
│ ├── 0003_profile_picture.py
│ ├── 0004_employee.py
│ ├── 0005_auto_20180906_1552.py
│ └── __init__.py
├── models.py
├── serializers.py
├── tests.py
├── urls.py
└── views.py
├── ems
├── .project
├── __init__.py
├── decorators.py
├── settings.py
├── static
│ └── css
│ │ └── custom.css
├── templates
│ ├── auth
│ │ ├── login.html
│ │ ├── profile.html
│ │ ├── profile_update.html
│ │ └── success.html
│ ├── base.html
│ ├── employee
│ │ ├── add.html
│ │ ├── delete.html
│ │ ├── details.html
│ │ ├── edit.html
│ │ └── index.html
│ ├── header.html
│ └── polls
│ │ ├── details.html
│ │ ├── edit_poll.html
│ │ ├── index.html
│ │ ├── new_poll.html
│ │ └── poll.html
├── urls.py
└── wsgi.py
├── manage.py
├── poll
├── __init__.py
├── admin.py
├── api_urls.py
├── api_views.py
├── apps.py
├── context_processors.py
├── documents.py
├── forms.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20180203_1058.py
│ ├── 0003_auto_20180206_2134.py
│ ├── 0004_auto_20180212_1627.py
│ ├── 0005_auto_20180214_2152.py
│ ├── 0006_auto_20180415_1140.py
│ ├── 0007_auto_20180705_1601.py
│ ├── 0008_auto_20180909_0514.py
│ ├── 0009_auto_20181002_1544.py
│ └── __init__.py
├── models.py
├── serializers.py
├── templatetags
│ ├── __init__.py
│ └── poll_extras.py
├── tests.py
├── urls.py
└── views.py
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | db.sqlite3
2 | __pycache__
3 | .vscode
4 | .project
5 | static
6 | media
7 | whoosh_index
8 |
--------------------------------------------------------------------------------
/Deployment/apache-site.conf:
--------------------------------------------------------------------------------
1 |
2 | ServerAdmin
3 | ServerName
4 | DocumentRoot /srv
5 |
6 | Alias /static
7 | ">
8 | Options FollowSymLinks
9 | Order allow,deny
10 | Allow from all
11 | Require all granted
12 |
13 |
14 | Alias /media
15 | ">
16 | Options FollowSymLinks
17 | Order allow,deny
18 | Allow from all
19 | Require all granted
20 |
21 | ErrorLog ${APACHE_LOG_DIR}/apis_error.log
22 | CustomLog ${APACHE_LOG_DIR}/apis_access.log combined
23 |
24 | WSGIDaemonProcess python-home= python-path=
25 | WSGIProcessGroup
26 | WSGIScriptAlias /
27 |
28 | >
29 |
30 | Require all granted
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Deployment/ems_gunicorn_service:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | NAME="demo" # Name of the application
4 | DJANGODIR=/home/hardik/projects/demo # Django project directory
5 | SOCKFILE=/home/hardik/projects/demo/run/gunicorn.sock # we will communicte using this unix socket
6 | USER=hardik # the user to run as
7 | GROUP=hardik # the group to run as
8 | NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
9 | DJANGO_SETTINGS_MODULE=demo.settings # which settings file should Django use
10 | DJANGO_WSGI_MODULE=demo.wsgi # WSGI module name
11 |
12 | echo "Starting $NAME as `whoami`"
13 |
14 | # Activate the virtual environment
15 | cd $DJANGODIR
16 | Source ../venv/bin/activate
17 | export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
18 | export PYTHONPATH=$DJANGODIR:$PYTHONPATH
19 |
20 | # Create the run directory if it doesn't exist
21 | RUNDIR=$(dirname $SOCKFILE)
22 | test -d $RUNDIR || mkdir -p $RUNDIR
23 |
24 | # Start your Django Unicorn
25 | # Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
26 | exec /home/hardik/projects/venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
27 | --name $NAME \
28 | --workers $NUM_WORKERS \
29 | --user=$USER --group=$GROUP \
30 | --bind=$SOCKFILE \
31 | --log-level=debug \
32 | --log-file=-
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3-onbuild
2 |
3 | EXPOSE 8000
4 |
5 | CMD ["python", "./manage.py", "runserver", "0:8000"]
6 |
--------------------------------------------------------------------------------
/Dockerrun.aws.json:
--------------------------------------------------------------------------------
1 | {
2 | "AWSEBDockerrunVersion": "1",
3 | "Image": {
4 | "Name": "hnmpatel/ems",
5 | "Update": "true"
6 | },
7 | "Ports": [
8 | {
9 | "ContainerPort": "8000"
10 | }
11 | ],
12 | "Logging": "/var/log/nginx"
13 | }
14 |
--------------------------------------------------------------------------------
/READEME.md:
--------------------------------------------------------------------------------
1 | # Setup project and run with following steps
2 | ## Install virtual environment
3 | ```sudo apt install python-virtualenv```
4 |
5 | ## Setup virtual environment with python 3.6+
6 | ```virtualenv venv -p python3```
7 |
8 | ## Install python dependencies
9 | ```pip install -r requirements.txt```
10 |
11 | ## Migrate database
12 | ```python manage.py migrate```
13 |
14 | ## Run server
15 | ```python manage.py runserver 8000```
16 |
17 | ## Test on browser
18 | http://localhost:8000
19 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-leap-day
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ems",
3 | "description": "",
4 | "scripts": {
5 | },
6 | "env": {
7 | },
8 | "formation": {
9 | },
10 | "addons": [
11 |
12 | ],
13 | "buildpacks": [
14 | {
15 | "url": "git://github.com/heroku/heroku-buildpack-python.git"
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/employee/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aarav-tech/ems/0f43447b8d698e35bae12c0c8a3723e3b1f9c29c/employee/__init__.py
--------------------------------------------------------------------------------
/employee/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from employee.models import *
3 |
4 |
5 | admin.site.register(Profile)
--------------------------------------------------------------------------------
/employee/api_urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, include
2 | from employee.views import *
3 |
4 |
5 | urlpatterns = [
6 | path('employee/', EmployeeListView.as_view())
7 | ]
--------------------------------------------------------------------------------
/employee/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class EmployeeConfig(AppConfig):
5 | name = 'employee'
6 |
--------------------------------------------------------------------------------
/employee/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.core.exceptions import ValidationError
3 | from django.contrib.auth.models import User, Group
4 |
5 |
6 | class UserForm(forms.ModelForm):
7 | password = forms.CharField(widget=forms.PasswordInput)
8 | role = forms.ModelChoiceField(queryset=Group.objects.all())
9 |
10 | class Meta:
11 | model = User
12 | fields = ['first_name', 'last_name',
13 | 'email', 'username',
14 | 'password']
15 | # excludes = ['']
16 |
17 | label = {
18 | 'password': 'Password'
19 | }
20 |
21 | def __init__(self, *args, **kwargs):
22 | if kwargs.get('instance'):
23 | # We get the 'initial' keyword argument or initialize it
24 | # as a dict if it didn't exist.
25 | initial = kwargs.setdefault('initial', {})
26 | # The widget for a ModelMultipleChoiceField expects
27 | # a list of primary key for the selected data.
28 | if kwargs['instance'].groups.all():
29 | initial['role'] = kwargs['instance'].groups.all()[0]
30 | else:
31 | initial['role'] = None
32 |
33 | forms.ModelForm.__init__(self, *args, **kwargs)
34 |
35 |
36 | def save(self):
37 | password = self.cleaned_data.pop('password')
38 | role = self.cleaned_data.pop('role')
39 | u = super().save()
40 | u.groups.set([role])
41 |
42 | u.set_password(password)
43 | u.save()
44 | return u
45 |
46 |
--------------------------------------------------------------------------------
/employee/middlewares.py:
--------------------------------------------------------------------------------
1 | class RoleMiddleware:
2 | def __init__(self, get_response):
3 | self.get_response = get_response
4 | # One-time configuration and initialization.
5 |
6 | def __call__(self, request):
7 | """
8 | Code to be executed for each request before
9 | the view (and later middleware) are called.
10 | """
11 |
12 | response = self.get_response(request)
13 |
14 | """
15 | Code to be executed for each request/response after
16 | the view is called.
17 | """
18 |
19 | return response
20 |
21 | def process_view(self, request, view_func, *view_args, **view_kargs):
22 | """
23 | called just before Django calls the view.
24 | Return either none or HttpResponse
25 | """
26 | if request.user.is_authenticated:
27 | request.role = None
28 | groups = request.user.groups.all()
29 | if groups:
30 | request.role = groups[0].name
31 |
32 | # def process_exception(self, request, exception):
33 | # """
34 | # Called for the response if exception is raised by view.
35 | # Return either none or HttpResponse
36 | # """
37 | # pass
38 |
39 |
40 | # def process_template_response(self, request, response):
41 | # """
42 | # request - HttpRequest object.
43 | # response - TemplateResponse object
44 |
45 | # return templateresponse
46 | # use this for changing template or context if it is needed.
47 | # """
48 | # pass
--------------------------------------------------------------------------------
/employee/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.1 on 2018-02-06 16:04
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Profile',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('designation', models.CharField(max_length=20)),
21 | ('salary', models.IntegerField(blank=True, null=True)),
22 | ('user', models.OneToOneField(on_delete='models.CASCADE', to=settings.AUTH_USER_MODEL)),
23 | ],
24 | options={
25 | 'ordering': ('-salary',),
26 | },
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/employee/migrations/0002_auto_20180415_0554.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-04-15 05:54
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 | import django.db.models.deletion
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('employee', '0001_initial'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='profile',
17 | name='user',
18 | field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/employee/migrations/0003_profile_picture.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-06-02 15:25
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('employee', '0002_auto_20180415_0554'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='profile',
15 | name='picture',
16 | field=models.ImageField(blank=True, max_length=255, null=True, upload_to='pictures/%Y/%m/%d/'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/employee/migrations/0004_employee.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-07-16 15:37
2 |
3 | import django.contrib.auth.models
4 | from django.db import migrations
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('auth', '0009_alter_user_last_name_max_length'),
11 | ('employee', '0003_profile_picture'),
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Employee',
17 | fields=[
18 | ],
19 | options={
20 | 'proxy': True,
21 | 'indexes': [],
22 | 'ordering': ('last_name',),
23 | },
24 | bases=('auth.user',),
25 | managers=[
26 | ('objects', django.contrib.auth.models.UserManager()),
27 | ],
28 | ),
29 | ]
30 |
--------------------------------------------------------------------------------
/employee/migrations/0005_auto_20180906_1552.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-09-06 15:52
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('employee', '0004_employee'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterModelOptions(
14 | name='employee',
15 | options={'ordering': ('username',)},
16 | ),
17 | ]
18 |
--------------------------------------------------------------------------------
/employee/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aarav-tech/ems/0f43447b8d698e35bae12c0c8a3723e3b1f9c29c/employee/migrations/__init__.py
--------------------------------------------------------------------------------
/employee/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.contrib.auth.models import User
3 | from django.db.models.signals import post_save
4 | from django.dispatch import receiver
5 |
6 |
7 | class Profile(models.Model):
8 | user = models.OneToOneField(User, on_delete=models.CASCADE)
9 | designation = models.CharField(max_length=20, null=False, blank=False)
10 | salary = models.IntegerField(null=True, blank=True)
11 | picture = models.ImageField(upload_to='pictures/%Y/%m/%d/', max_length=255, null=True, blank=True)
12 |
13 | class Meta:
14 | ordering = ('-salary',)
15 |
16 | def __str__(self):
17 | return "{0} - {1}".format(self.user.username, self.designation)
18 |
19 |
20 |
21 | class EmployeeManager(models.Manager):
22 | def get_queryset(self):
23 | return super().get_queryset().filter(profile__designation="Employee")
24 |
25 | class Employee(User):
26 | class Meta:
27 | ordering = ("username",)
28 | proxy = True
29 |
30 | objects = EmployeeManager()
31 |
32 | def full_name(self):
33 | return self.first_name + " - " + self.last_name
34 |
35 |
36 | @receiver(post_save, sender=User)
37 | def user_is_created(sender, instance, created, **kwargs):
38 | print(created)
39 | if created:
40 | Profile.objects.create(user=instance)
41 | else:
42 | instance.profile.save()
43 |
44 |
45 | from django.contrib.auth.models import User
46 |
47 | @property
48 | def full_name(self):
49 | return "{} {}".format(self.first_name, self.last_name)
50 |
51 | User.add_to_class('full_name', full_name)
--------------------------------------------------------------------------------
/employee/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework import serializers
2 |
3 | from django.contrib.auth.models import User
4 | from django.contrib.auth import authenticate
5 | from rest_framework import exceptions
6 | from .models import Profile
7 |
8 |
9 | class ProfileSerializer(serializers.ModelSerializer):
10 | class Meta:
11 | model = Profile
12 | fields = ['salary', 'designation', 'picture']
13 |
14 | class EmployeeSerializer(serializers.ModelSerializer):
15 | profile = ProfileSerializer()
16 |
17 | class Meta:
18 | model = User
19 | fields = ['username', 'first_name',
20 | 'last_name', 'profile', 'email',
21 | 'is_staff', 'is_active', 'date_joined',
22 | 'is_superuser']
23 |
24 |
25 | class LoginSerializer(serializers.Serializer):
26 | username = serializers.CharField()
27 | password = serializers.CharField()
28 |
29 | def validate(self, data):
30 | username = data.get("username", "")
31 | password = data.get("password", "")
32 |
33 | if username and password:
34 | user = authenticate(username=username, password=password)
35 | if user:
36 | if user.is_active:
37 | data["user"] = user
38 | else:
39 | msg = "User is deactivated."
40 | raise exceptions.ValidationError(msg)
41 | else:
42 | msg = "Unable to login with given credentials."
43 | raise exceptions.ValidationError(msg)
44 | else:
45 | msg = "Must provide username and password both."
46 | raise exceptions.ValidationError(msg)
47 | return data
--------------------------------------------------------------------------------
/employee/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/employee/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from employee.views import *
3 |
4 | urlpatterns = [
5 | path('', employee_list, name='employee_list'),
6 | path('/details/', employee_details, name="employee_details"),
7 | path('/edit/', employee_edit, name="employee_edit"),
8 | path('add/', employee_add, name="employee_add"),
9 | path('/delete/', employee_delete, name="employee_delete"),
10 | ]
--------------------------------------------------------------------------------
/employee/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, get_object_or_404
2 | from django.http import HttpResponseRedirect
3 | from django.contrib.auth.models import User
4 | from django.contrib.auth import authenticate, login, logout
5 | from django.contrib.auth.decorators import login_required
6 | from django.views.generic import DetailView, ListView
7 | from django.views.generic.edit import UpdateView
8 | from django.urls import reverse
9 | from django.urls import reverse_lazy
10 | from employee.forms import UserForm
11 | from ems.decorators import admin_hr_required, admin_only
12 |
13 | def index(request):
14 | return HttpResponseRedirect(reverse('employee_list'))
15 |
16 | def user_login(request):
17 | context = {}
18 | if request.method == "POST":
19 | username = request.POST['username']
20 | password = request.POST['password']
21 | user = authenticate(request, username=username, password=password)
22 | if user:
23 | login(request, user)
24 | if request.GET.get('next', None):
25 | return HttpResponseRedirect(request.GET['next'])
26 | return HttpResponseRedirect(reverse('employee_list'))
27 | else:
28 | context["error"] = "Provide valid credentials !!"
29 | return render(request, "auth/login.html", context)
30 | else:
31 | return render(request, "auth/login.html", context)
32 |
33 | @login_required(login_url="/login/")
34 | def success(request):
35 | context = {}
36 | context['user'] = request.user
37 | return render(request, "auth/success.html", context)
38 |
39 | def user_logout(request):
40 | logout(request)
41 | return HttpResponseRedirect(reverse('user_login'))
42 |
43 |
44 | @login_required(login_url="/login/")
45 | def employee_list(request):
46 | print(request.role)
47 | context = {}
48 | context['users'] = User.objects.all()
49 | context['title'] = 'Employees'
50 | return render(request, 'employee/index.html', context)
51 |
52 | @login_required(login_url="/login/")
53 | def employee_details(request, id=None):
54 | context = {}
55 | context['user'] = get_object_or_404(User, id=id)
56 | return render(request, 'employee/details.html', context)
57 |
58 | @login_required(login_url="/login/")
59 | @admin_only
60 | def employee_add(request):
61 | context = {}
62 | if request.method == 'POST':
63 | user_form = UserForm(request.POST)
64 | context['user_form'] = user_form
65 | if user_form.is_valid():
66 | u = user_form.save()
67 | return HttpResponseRedirect(reverse('employee_list'))
68 | else:
69 | return render(request, 'employee/add.html', context)
70 | else:
71 | user_form = UserForm()
72 | context['user_form'] = user_form
73 | return render(request, 'employee/add.html', context)
74 |
75 | @login_required(login_url="/login/")
76 | def employee_edit(request, id=None):
77 | user = get_object_or_404(User, id=id)
78 | if request.method == 'POST':
79 | user_form = UserForm(request.POST, instance=user)
80 | if user_form.is_valid():
81 | user_form.save()
82 | return HttpResponseRedirect(reverse('employee_list'))
83 | else:
84 | return render(request, 'employee/edit.html', {"user_form": user_form})
85 | else:
86 | user_form = UserForm(instance=user)
87 | return render(request, 'employee/edit.html', {"user_form": user_form})
88 |
89 | @login_required(login_url="/login/")
90 | def employee_delete(request, id=None):
91 | user = get_object_or_404(User, id=id)
92 | if request.method == 'POST':
93 | user.delete()
94 | return HttpResponseRedirect(reverse('employee_list'))
95 | else:
96 | context = {}
97 | context['user'] = user
98 | return render(request, 'employee/delete.html', context)
99 |
100 |
101 | class ProfileUpdate(UpdateView):
102 | fields = ['designation', 'salary', 'picture']
103 | template_name = 'auth/profile_update.html'
104 | success_url = reverse_lazy('my_profile')
105 |
106 | def get_object(self):
107 | return self.request.user.profile
108 |
109 |
110 |
111 | class MyProfile(DetailView):
112 | template_name = 'auth/profile.html'
113 |
114 | def get_object(self):
115 | return self.request.user.profile
116 |
117 |
118 | from rest_framework.views import APIView
119 | from rest_framework.generics import GenericAPIView
120 | from .serializers import LoginSerializer
121 | from django.contrib.auth import login as django_login, logout as django_logout
122 | from rest_framework.authtoken.models import Token
123 | from rest_framework.authentication import TokenAuthentication
124 | from rest_framework.response import Response
125 | from rest_framework import generics
126 | from .serializers import EmployeeSerializer
127 | from django_filters.rest_framework import DjangoFilterBackend
128 | from rest_framework.filters import OrderingFilter, SearchFilter
129 | from django_filters import FilterSet
130 | from django_filters import rest_framework as filters
131 |
132 |
133 | class LoginView(GenericAPIView):
134 | serializer_class = LoginSerializer
135 |
136 | def post(self, request):
137 | serializer = LoginSerializer(data=request.data)
138 | serializer.is_valid(raise_exception=True)
139 | user = serializer.validated_data["user"]
140 | django_login(request, user)
141 | token, created = Token.objects.get_or_create(user=user)
142 | return Response({"token": token.key}, status=200)
143 |
144 |
145 | class LogoutView(APIView):
146 | authentication_classes = (TokenAuthentication, )
147 |
148 | def post(self, request):
149 | django_logout(request)
150 | return Response(status=204)
151 |
152 | class EmployeeFilter(FilterSet):
153 | is_active = filters.CharFilter('is_active')
154 | designation = filters.CharFilter('profile__designation')
155 | min_salary = filters.CharFilter(method="filter_by_min_salary")
156 | max_salary = filters.CharFilter(method="filter_by_max_salary")
157 |
158 | class Meta:
159 | model = User
160 | fields = ('is_active', 'designation', 'username',)
161 |
162 | def filter_by_min_salary(self, queryset, name, value):
163 | queryset = queryset.filter(profile__salary__gt=value)
164 | return queryset
165 |
166 | def filter_by_max_salary(self, queryset, name, value):
167 | queryset = queryset.filter(profile__salary__lt=value)
168 | return queryset
169 |
170 |
171 | class EmployeeListView(generics.ListAPIView):
172 | serializer_class = EmployeeSerializer
173 | queryset = User.objects.all()
174 | filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter)
175 | # filter_fields = ('is_active', 'profile__designation', )
176 | filter_class = EmployeeFilter
177 |
178 | ordering_fields = ('is_active', 'username')
179 | ordering = ('username',)
180 | search_fields = ('username', 'first_name')
181 |
182 |
183 | # def get_queryset(self):
184 | # queryset = User.objects.all()
185 | # active = self.request.query_params.get('is_active', '')
186 | # if active:
187 | # if active == "False":
188 | # active = False
189 | # elif active == "True":
190 | # active = True
191 | # else:
192 | # return queryset
193 | # return queryset.filter(is_active=active)
194 | # return queryset
195 |
--------------------------------------------------------------------------------
/ems/.project:
--------------------------------------------------------------------------------
1 | /home/hardik-p/projects/mine/ems
2 |
--------------------------------------------------------------------------------
/ems/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aarav-tech/ems/0f43447b8d698e35bae12c0c8a3723e3b1f9c29c/ems/__init__.py
--------------------------------------------------------------------------------
/ems/decorators.py:
--------------------------------------------------------------------------------
1 | from django.http import HttpResponseRedirect
2 | from django.urls import reverse
3 | from django.core.exceptions import PermissionDenied
4 |
5 | def admin_hr_required(view_func):
6 | def wrap(request, *args, **kwargs):
7 | allowed_roles=["Admin", "HR"]
8 | if request.role in allowed_roles:
9 | return view_func(request, *args, **kwargs)
10 | else:
11 | return HttpResponseRedirect(reverse('employee_list'))
12 | return wrap
13 |
14 | def admin_only(view_func):
15 | def wrap(request, *args, **kwargs):
16 | if request.role == "Admin":
17 | return view_func(request, *args, **kwargs)
18 | else:
19 | return HttpResponseRedirect(reverse('employee_list'))
20 | return wrap
21 |
--------------------------------------------------------------------------------
/ems/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for ems project.
3 |
4 | Generated by 'django-admin startproject' using Django 2.0.1.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/2.0/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = '#c=44^9m)58=k5el2oi&0b7kr=clo%^m#5repy5ytkymok-v4e'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = ["*"]
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'rest_framework_swagger',
41 |
42 | # 'haystack',
43 |
44 | 'poll',
45 | 'employee',
46 | 'rest_framework',
47 | 'rest_framework.authtoken',
48 | 'django_extensions',
49 | 'django_filters',
50 | # 'django_elasticsearch_dsl',
51 |
52 | 'material.theme.amber',
53 | 'material',
54 | ]
55 |
56 | MIDDLEWARE = [
57 | 'django.middleware.security.SecurityMiddleware',
58 | 'django.contrib.sessions.middleware.SessionMiddleware',
59 | 'django.middleware.common.CommonMiddleware',
60 | 'django.middleware.csrf.CsrfViewMiddleware',
61 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
62 | 'django.contrib.messages.middleware.MessageMiddleware',
63 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
64 | 'employee.middlewares.RoleMiddleware'
65 | ]
66 |
67 | ROOT_URLCONF = 'ems.urls'
68 |
69 | TEMPLATES = [
70 | {
71 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
72 | 'APP_DIRS': True,
73 | 'DIRS': [
74 | os.path.join(BASE_DIR, 'ems', 'templates'),
75 | ],
76 | 'OPTIONS': {
77 | 'context_processors': [
78 | 'django.template.context_processors.debug',
79 | 'django.template.context_processors.request',
80 | 'django.contrib.auth.context_processors.auth',
81 | 'django.contrib.messages.context_processors.messages',
82 | 'poll.context_processors.polls_count'
83 | ],
84 | },
85 | },
86 | ]
87 |
88 | WSGI_APPLICATION = 'ems.wsgi.application'
89 |
90 |
91 | # Database
92 | # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
93 |
94 | DATABASES = {
95 | 'default': {
96 | 'ENGINE': 'django.db.backends.sqlite3',
97 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
98 | }
99 | }
100 |
101 |
102 | # Password validation
103 | # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
104 |
105 | AUTH_PASSWORD_VALIDATORS = [
106 | {
107 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
108 | },
109 | {
110 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
111 | },
112 | {
113 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
114 | },
115 | {
116 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
117 | },
118 | ]
119 |
120 |
121 | # Internationalization
122 | # https://docs.djangoproject.com/en/2.0/topics/i18n/
123 |
124 | LANGUAGE_CODE = 'en-us'
125 |
126 | TIME_ZONE = 'UTC'
127 |
128 | USE_I18N = True
129 |
130 | USE_L10N = True
131 |
132 | USE_TZ = True
133 |
134 |
135 | # Static files (CSS, JavaScript, Images)
136 | # https://docs.djangoproject.com/en/2.0/howto/static-files/
137 |
138 | STATIC_URL = '/static/'
139 | STATIC_ROOT = 'static'
140 |
141 | MEDIA_URL = '/media/'
142 | MEDIA_ROOT = 'media'
143 |
144 | LOGIN_URL = '/login/'
145 |
146 | REST_FRAMEWORK = {
147 | 'DEFAULT_AUTHENTICATION_CLASSES': (
148 | 'rest_framework.authentication.TokenAuthentication',
149 | 'rest_framework.authentication.BasicAuthentication',
150 | 'rest_framework.authentication.SessionAuthentication',
151 | ),
152 | 'DEFAULT_PAGINATION_CLASS':
153 | 'rest_framework.pagination.PageNumberPagination',
154 | 'PAGE_SIZE': 100,
155 | 'ORDERING_PARAM': 'ordering',
156 | }
157 |
158 |
159 | ELASTICSEARCH_DSL={
160 | 'default': {
161 | 'hosts': 'localhost:9200'
162 | },
163 | }
164 |
165 | SWAGGER_SETTINGS = {
166 | 'SECURITY_DEFINITIONS': {
167 | 'api_key': {
168 | "type": "apiKey",
169 | "name": "Authorization",
170 | "in": "header"
171 | }
172 | },
173 | }
--------------------------------------------------------------------------------
/ems/static/css/custom.css:
--------------------------------------------------------------------------------
1 | .brand-logo {
2 | position: relative !important;
3 | }
--------------------------------------------------------------------------------
/ems/templates/auth/login.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 | Employee Management System
5 |
6 |
7 |
8 |
9 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ems/templates/auth/profile.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 | My Profile
7 |
8 |
9 |
10 | First Name |
11 | {{object.user.first_name}} |
12 |
13 |
14 | Last Name |
15 | {{object.user.last_name}} |
16 |
17 |
18 | Email Id |
19 | {{object.user.email}} |
20 |
21 |
22 | Salary |
23 | {{object.salary}} |
24 |
25 |
26 | Designation |
27 | {{object.designation}} |
28 |
29 |
30 | Profile Picture |
31 |
32 | {% if object.picture %}
33 |
34 | {% endif %}
35 | |
36 |
37 |
38 |
39 |
42 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/auth/profile_update.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
14 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/auth/success.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 | User {{user.username}} is logged in successfully.
6 |
10 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/base.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 | Employee Management System
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {% include 'header.html' %}
13 |
14 |
15 | {% block content %}
16 | {% endblock content %}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ems/templates/employee/add.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
14 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/employee/delete.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 | {{user.first_name}} {{user.last_name}}
7 |
12 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/employee/details.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
7 |
8 |
9 | First Name |
10 | {{user.first_name}} |
11 |
12 |
13 | Last Name |
14 | {{user.last_name}} |
15 |
16 |
17 | Email Id |
18 | {{user.email}} |
19 |
20 |
21 | Salary |
22 | {{user.profile.salary}} |
23 |
24 |
25 | Designation |
26 | {{user.profile.designation}} |
27 |
28 |
29 |
30 |
31 |
Edit
32 |
Delete
33 |
34 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/employee/edit.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% load material_form %}
3 |
4 |
5 | {% block content %}
6 |
7 |
15 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/employee/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% load poll_extras %}
3 |
4 |
5 | {% block content %}
6 |
7 |
8 |
9 |
List of {{title}}
10 | {% if request.role == 'Admin' %}
11 |
Add employee
12 | {% endif %}
13 |
14 |
15 | {% if users %}
16 |
17 |
18 |
19 | Name |
20 | Actions |
21 |
22 |
23 |
24 | {% for user in users %}
25 |
26 |
27 | {{user.first_name}} {{user.last_name}}
28 | {{user.email}}
29 |
30 | |
31 | Details
32 | Edit
33 | Delete
34 | |
35 |
36 | {% endfor %}
37 |
38 |
39 | {% else %}
40 |
There is no employee available.
41 | {% endif %}
42 |
43 |
44 |
45 | {% recent_polls 1 name="hardik patel" as questions %}
46 |
47 |
Recent Polls
48 |
49 | {% if questions %}
50 |
55 | {% else %}
56 |
There is no poll available.
57 | {% endif %}
58 |
59 |
60 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/header.html:
--------------------------------------------------------------------------------
1 | {% load poll_extras %}
2 |
--------------------------------------------------------------------------------
/ems/templates/polls/details.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
{{question.title}}
7 |
8 |
19 |
20 | Created by: {{question.created_by.first_name}}
21 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/polls/edit_poll.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
17 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/polls/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
List of {{title}}
7 |
8 |
9 |
10 | {% if questions %}
11 |
12 |
13 |
14 | Poll |
15 | Actions |
16 |
17 |
18 |
19 | {% for question in questions %}
20 |
21 |
22 | {{question.title}}
23 | |
24 |
25 | Details
26 | Edit
27 | Delete
28 | |
29 |
30 | {% endfor %}
31 |
32 |
33 | {% else %}
34 |
There is no question available.
35 | {% endif %}
36 |
37 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/polls/new_poll.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
17 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/templates/polls/poll.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
{{question.title}}
7 |
8 |
22 | {% endblock content %}
--------------------------------------------------------------------------------
/ems/urls.py:
--------------------------------------------------------------------------------
1 | """ems URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/2.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.contrib import admin
17 | from django.urls import path, include
18 | from rest_framework.schemas import get_schema_view
19 | from django.conf.urls.static import static
20 | from rest_framework_swagger.views import get_swagger_view
21 |
22 | from django.conf import settings
23 |
24 |
25 | from employee.views import ( index, user_login, user_logout,
26 | success, ProfileUpdate, MyProfile, LoginView, LogoutView)
27 |
28 | schema_view = get_swagger_view(title='EMS API Documentation')
29 |
30 | urlpatterns = [
31 | path('api_documentation/', schema_view),
32 | path('', index, name='home'),
33 | path('admin/', admin.site.urls),
34 | path('poll/', include('poll.urls')),
35 | path('api/v1/', include('poll.api_urls')),
36 | path('api/v1/', include('employee.api_urls')),
37 | # path('api/v1/auth/', include('rest_auth.urls')),
38 | path('api/v1/auth/login/', LoginView.as_view()),
39 | path('api/v1/auth/logout/', LogoutView.as_view()),
40 | path('employee/', include('employee.urls')),
41 |
42 | path('login/', user_login, name="user_login"),
43 | path('success/', success, name="user_success"),
44 | path('logout/', user_logout, name="user_logout"),
45 | path('profile/', MyProfile.as_view(), name="my_profile"),
46 | path('profile/update', ProfileUpdate.as_view(), name="update_profile"),
47 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
48 |
49 | urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
50 |
--------------------------------------------------------------------------------
/ems/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for ems 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/2.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", "ems.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ems.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError as exc:
10 | raise ImportError(
11 | "Couldn't import Django. Are you sure it's installed and "
12 | "available on your PYTHONPATH environment variable? Did you "
13 | "forget to activate a virtual environment?"
14 | ) from exc
15 | execute_from_command_line(sys.argv)
16 |
--------------------------------------------------------------------------------
/poll/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aarav-tech/ems/0f43447b8d698e35bae12c0c8a3723e3b1f9c29c/poll/__init__.py
--------------------------------------------------------------------------------
/poll/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from poll.models import *
3 |
4 | admin.site.register(Question)
5 | admin.site.register(Choice)
6 | admin.site.register(Answer)
7 | admin.site.register(Tag)
--------------------------------------------------------------------------------
/poll/api_urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, include
2 | from poll.views import *
3 |
4 | from rest_framework.routers import DefaultRouter, SimpleRouter
5 |
6 | router = DefaultRouter()
7 | router.register('poll', PollViewSet)
8 |
9 |
10 | poll_list_view = PollViewSet.as_view({
11 | "get": "list",
12 | "post": "create"
13 | })
14 |
15 | urlpatterns = [
16 | path('', include(router.urls)),
17 | # path('poll/', PollAPIView.as_view()),
18 | # path('poll//', PollDetailView.as_view()),
19 | # path('generics/poll/', poll_list_view),
20 | # path('generics/poll//', PollListView.as_view()),
21 | # path('poll/search/', QuestionSearchViewSet.as_view({'get': 'list'})),
22 | ]
--------------------------------------------------------------------------------
/poll/api_views.py:
--------------------------------------------------------------------------------
1 | from django_filters.rest_framework import DjangoFilterBackend
2 | from django_filters import FilterSet
3 | from django_filters import rest_framework as filters
4 |
5 | from rest_framework.parsers import JSONParser
6 | from rest_framework.views import APIView
7 | from rest_framework.response import Response
8 | from rest_framework import status
9 | from rest_framework import generics
10 | from rest_framework import mixins
11 | from rest_framework.decorators import action
12 | from rest_framework.authentication import (
13 | SessionAuthentication,
14 | BasicAuthentication,
15 | TokenAuthentication,
16 | )
17 | from rest_framework.permissions import IsAuthenticated, IsAdminUser
18 | from rest_framework import viewsets
19 | from rest_framework.decorators import action
20 |
21 | from poll.forms import PollForm, ChoiceForm
22 | from poll.models import *
23 | from poll.serializers import (
24 | QuestionSerializer,
25 | ChoiceSerializer,
26 | QuestionSearchSerializer,
27 | )
28 |
29 |
30 | class QuestionSearchViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
31 | serializer_class = QuestionSearchSerializer
32 |
33 | def get_queryset(self):
34 | result = QuestionDocument.search()
35 |
36 |
37 | class PollFilter(FilterSet):
38 | tags = filters.CharFilter(method="filter_by_tags")
39 |
40 | class Meta:
41 | model = Question
42 | fields = ["tags"]
43 |
44 | def filter_by_tags(self, queryset, name, value):
45 | tag_names = value.strip().split(",")
46 | tags = Tag.objects.filter(name__in=tag_names)
47 | return queryset.filter(tags__in=tags).distinct()
48 |
49 |
50 | class PollViewSet(viewsets.ModelViewSet):
51 | serializer_class = QuestionSerializer
52 | queryset = Question.objects.all()
53 | lookup_field = "id"
54 | filter_backends = (DjangoFilterBackend,)
55 | filter_class = PollFilter
56 | authentication_classes = (TokenAuthentication,)
57 |
58 | @action(detail=True, methods=["GET"])
59 | def choices(self, request, id=None):
60 | question = self.get_object()
61 | choices = Choice.objects.filter(question=question)
62 | serializer = ChoiceSerializer(choices, many=True)
63 | return Response(serializer.data, status=200)
64 |
65 | @action(detail=True, methods=["POST"])
66 | def choice(self, request, id=None):
67 | question = self.get_object()
68 | data = request.data
69 | data["question"] = question.id
70 | serializer = ChoiceSerializer(data=data)
71 | if serializer.is_valid():
72 | serializer.save()
73 | return Response(serializer.data, status=201)
74 | return Response(serializer.erros, status=400)
75 |
76 | class PollListView(
77 | generics.GenericAPIView,
78 | mixins.ListModelMixin,
79 | mixins.CreateModelMixin,
80 | mixins.RetrieveModelMixin,
81 | mixins.UpdateModelMixin,
82 | mixins.DestroyModelMixin,
83 | ):
84 | serializer_class = QuestionSerializer
85 | queryset = Question.objects.all()
86 | lookup_field = "id"
87 | authentication_classes = [
88 | TokenAuthentication,
89 | SessionAuthentication,
90 | BasicAuthentication,
91 | ]
92 | permission_classes = [IsAuthenticated, IsAdminUser]
93 |
94 |
95 | def get(self, request, id=None):
96 | if id:
97 | return self.retrieve(request, id)
98 | else:
99 | return self.list(request)
100 |
101 | def post(self, request):
102 | return self.create(request)
103 |
104 | def perform_create(self, serializer):
105 | serializer.save(created_by=self.request.user)
106 |
107 | def put(self, request, id=None):
108 | return self.update(request, id)
109 |
110 | def perform_update(self, serializer):
111 | print(self.request.user)
112 | serializer.save(created_by=self.request.user)
113 |
114 | def delete(self, request, id=None):
115 | return self.destroy(request, id)
116 |
117 |
118 | class PollAPIView(APIView):
119 | def get(self, request):
120 | questions = Question.objects.all()
121 | serailizer = QuestionSerializer(questions, many=True)
122 | return Response(serailizer.data, status=200)
123 |
124 | def post(self, request):
125 | data = request.data
126 | serializer = QuestionSerializer(data=data)
127 | if serializer.is_valid():
128 | serializer.save()
129 | return Response(serializer.data, status=201)
130 | return Response(serializer.erros, status=400)
131 |
132 |
133 | class PollDetailView(APIView):
134 | def get_object(self, id):
135 | try:
136 | return Question.objects.get(id=id)
137 | except Question.DoesNotExist as e:
138 | return Response({"error": "Given question object not found."}, status=404)
139 |
140 | def get(self, request, id=None):
141 | instance = self.get_object(id)
142 | serailizer = QuestionSerializer(instance)
143 | return Response(serailizer.data)
144 |
145 | def put(self, request, id=None):
146 | data = request.data
147 | instance = self.get_object(id)
148 | serializer = QuestionSerializer(instance, data=data)
149 | if serializer.is_valid():
150 | serializer.save()
151 | return Response(serializer.data, status=200)
152 | return Response(serializer.erros, status=400)
153 |
154 | def delete(self, request, id=None):
155 | instance = self.get_object(id)
156 | instance.delete()
157 | return HttpResponse(status=204)
158 |
159 |
160 | @csrf_exempt
161 | def poll(request):
162 | if request.method == "GET":
163 | questions = Question.objects.all()
164 | serailizer = QuestionSerializer(questions, many=True)
165 | return JsonResponse(serailizer.data, safe=False)
166 |
167 | elif request.method == "POST":
168 | json_parser = JSONParser()
169 | data = json_parser.parse(request)
170 | serializer = QuestionSerializer(data=data)
171 | if serializer.is_valid():
172 | serializer.save()
173 | return JsonResponse(serializer.data, status=201)
174 | return JsonResponse(serializer.errors, status=400)
175 |
176 |
177 | @csrf_exempt
178 | def poll_details(request, id):
179 | try:
180 | instance = Question.objects.get(id=id)
181 | except Question.DoesNotExist as e:
182 | return JsonResponse({"error": "Given question object not found."}, status=404)
183 |
184 | if request.method == "GET":
185 | serailizer = QuestionSerializer(instance)
186 | return JsonResponse(serailizer.data)
187 |
188 | elif request.method == "PUT":
189 | json_parser = JSONParser()
190 | data = json_parser.parse(request)
191 | serializer = QuestionSerializer(instance, data=data)
192 | if serializer.is_valid():
193 | serializer.save()
194 | return JsonResponse(serializer.data, status=200)
195 | return JsonResponse(serializer.erros, status=400)
196 |
197 | elif request.method == "DELETE":
198 | instance.delete()
199 | return HttpResponse(status=204)
200 |
--------------------------------------------------------------------------------
/poll/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class PollConfig(AppConfig):
5 | name = 'poll'
6 |
--------------------------------------------------------------------------------
/poll/context_processors.py:
--------------------------------------------------------------------------------
1 | from poll.models import Question
2 |
3 | def polls_count(request):
4 | count = Question.objects.count()
5 | print("Polls count - ", count)
6 | return {"polls_count": count}
--------------------------------------------------------------------------------
/poll/documents.py:
--------------------------------------------------------------------------------
1 | from django_elasticsearch_dsl import DocType, Index
2 | from .models import Question
3 |
4 |
5 | questions = Index('questions')
6 | questions.settings(
7 | number_of_shards=1,
8 | number_of_replicas=0
9 | )
10 |
11 | @questions.doc_type
12 | class QuestionDocument(DocType):
13 | class Meta:
14 | model = Question
15 | fields = [
16 | 'id',
17 | 'title',
18 | 'status',
19 | 'created_at'
20 | ]
--------------------------------------------------------------------------------
/poll/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from poll.models import Question, Choice
3 |
4 | class PollForm(forms.ModelForm):
5 | title = forms.CharField(max_length=255, label='Question')
6 |
7 | class Meta:
8 | model = Question
9 | fields = ['title']
10 |
11 | class ChoiceForm(forms.ModelForm):
12 | text = forms.CharField(
13 | max_length=255, label="Choice")
14 |
15 | class Meta:
16 | model = Choice
17 | exclude = ('question',)
--------------------------------------------------------------------------------
/poll/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.1 on 2018-02-03 05:07
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Question',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('title', models.TextField(blank=True, null=True)),
21 | ('status', models.CharField(default='inactive', max_length=10)),
22 | ('created_at', models.DateTimeField(auto_now_add=True)),
23 | ('updated_at', models.DateTimeField(auto_now=True)),
24 | ('created_by', models.ForeignKey(blank=True, null=True, on_delete='CASCADE', to=settings.AUTH_USER_MODEL)),
25 | ],
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/poll/migrations/0002_auto_20180203_1058.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.1 on 2018-02-03 05:28
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('poll', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='Choice',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('text', models.TextField(blank=True, null=True)),
18 | ('created_at', models.DateTimeField(auto_now_add=True)),
19 | ('updated_at', models.DateTimeField(auto_now=True)),
20 | ],
21 | ),
22 | migrations.AddField(
23 | model_name='question',
24 | name='end_date',
25 | field=models.DateTimeField(blank=True, null=True),
26 | ),
27 | migrations.AddField(
28 | model_name='question',
29 | name='start_date',
30 | field=models.DateTimeField(blank=True, null=True),
31 | ),
32 | migrations.AddField(
33 | model_name='choice',
34 | name='question',
35 | field=models.ForeignKey(on_delete='CASCADE', to='poll.Question'),
36 | ),
37 | ]
38 |
--------------------------------------------------------------------------------
/poll/migrations/0003_auto_20180206_2134.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.1 on 2018-02-06 16:04
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('poll', '0002_auto_20180203_1058'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='question',
16 | name='created_by',
17 | field=models.ForeignKey(blank=True, null=True, on_delete='models.CASCADE', to=settings.AUTH_USER_MODEL),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/poll/migrations/0004_auto_20180212_1627.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.1 on 2018-02-12 10:57
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('poll', '0003_auto_20180206_2134'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='choice',
15 | name='question',
16 | field=models.ForeignKey(on_delete='models.CASCADE', to='poll.Question'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/poll/migrations/0005_auto_20180214_2152.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.1 on 2018-02-14 16:22
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 | import django.db.models.deletion
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12 | ('poll', '0004_auto_20180212_1627'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Answer',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('created_at', models.DateTimeField(auto_now_add=True)),
21 | ('updated_at', models.DateTimeField(auto_now=True)),
22 | ],
23 | ),
24 | migrations.AlterField(
25 | model_name='choice',
26 | name='question',
27 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='poll.Question'),
28 | ),
29 | migrations.AlterField(
30 | model_name='question',
31 | name='created_by',
32 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
33 | ),
34 | migrations.AddField(
35 | model_name='answer',
36 | name='choice',
37 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='poll.Choice'),
38 | ),
39 | migrations.AddField(
40 | model_name='answer',
41 | name='user',
42 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
43 | ),
44 | ]
45 |
--------------------------------------------------------------------------------
/poll/migrations/0006_auto_20180415_1140.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-04-15 11:40
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('poll', '0005_auto_20180214_2152'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='question',
15 | name='title',
16 | field=models.TextField(default=1),
17 | preserve_default=False,
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/poll/migrations/0007_auto_20180705_1601.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-07-05 16:01
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('poll', '0006_auto_20180415_1140'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='Tag',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('name', models.CharField(max_length=50)),
18 | ],
19 | ),
20 | migrations.AddField(
21 | model_name='question',
22 | name='tags',
23 | field=models.ManyToManyField(to='poll.Tag'),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/poll/migrations/0008_auto_20180909_0514.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-09-09 05:14
2 |
3 | from django.db import migrations, models
4 | import django.utils.timezone
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('poll', '0007_auto_20180705_1601'),
11 | ]
12 |
13 | operations = [
14 | migrations.AddField(
15 | model_name='tag',
16 | name='created_at',
17 | field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
18 | preserve_default=False,
19 | ),
20 | migrations.AddField(
21 | model_name='tag',
22 | name='updated_at',
23 | field=models.DateTimeField(auto_now=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/poll/migrations/0009_auto_20181002_1544.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-10-02 15:44
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('contenttypes', '0002_remove_content_type_name'),
11 | ('poll', '0008_auto_20180909_0514'),
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Comment',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('text', models.TextField()),
20 | ('object_id', models.PositiveIntegerField()),
21 | ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
22 | ],
23 | ),
24 | migrations.AlterModelOptions(
25 | name='question',
26 | options={'ordering': ('-created_at',)},
27 | ),
28 | migrations.AlterModelOptions(
29 | name='tag',
30 | options={'ordering': []},
31 | ),
32 | ]
33 |
--------------------------------------------------------------------------------
/poll/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aarav-tech/ems/0f43447b8d698e35bae12c0c8a3723e3b1f9c29c/poll/migrations/__init__.py
--------------------------------------------------------------------------------
/poll/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.contrib.auth.models import User
3 | from django.contrib.contenttypes.models import ContentType
4 | from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
5 |
6 |
7 | class ObjectTracking(models.Model):
8 | created_at = models.DateTimeField(auto_now_add=True)
9 | updated_at = models.DateTimeField(auto_now=True)
10 |
11 | class Meta:
12 | abstract = True
13 | ordering = ('-created_at',)
14 |
15 | class Comment(models.Model):
16 | text = models.TextField(null=False, blank=False)
17 |
18 | content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
19 | object_id = models.PositiveIntegerField()
20 | content_object = GenericForeignKey('content_type', 'object_id')
21 |
22 | def __str__(self):
23 | return self.text[:20]
24 |
25 | class Tag(ObjectTracking):
26 | name = models.CharField(max_length=50)
27 |
28 | def __str__(self):
29 | return self.name
30 |
31 | class Meta:
32 | ordering = []
33 |
34 | class QuestionManager(models.Manager):
35 | def get_queryset(self):
36 | return super().get_queryset().filter(status="active")
37 |
38 | def all_objects(self):
39 | return super().get_queryset()
40 |
41 | def inactive(self):
42 | return self.all_objects().filter(status='inactive')
43 |
44 |
45 |
46 | class Question(ObjectTracking):
47 | title = models.TextField(null=False, blank=False)
48 | status = models.CharField(default='inactive', max_length=10)
49 | created_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
50 |
51 | start_date = models.DateTimeField(null=True, blank=True)
52 | end_date = models.DateTimeField(null=True, blank=True)
53 | tags = models.ManyToManyField(Tag)
54 |
55 | comments = GenericRelation(Comment, related_query_name="question")
56 |
57 | objects = QuestionManager()
58 |
59 |
60 | def __str__(self):
61 | return self.title
62 |
63 | @property
64 | def choices(self):
65 | return self.choice_set.all()
66 |
67 |
68 | class Choice(models.Model):
69 | question = models.ForeignKey('poll.Question', on_delete=models.CASCADE)
70 | text = models.TextField(null=True, blank=True)
71 |
72 | created_at = models.DateTimeField(auto_now_add=True)
73 | updated_at = models.DateTimeField(auto_now=True)
74 |
75 | def __str__(self):
76 | return self.text
77 |
78 | @property
79 | def votes(self):
80 | return self.answer_set.count()
81 |
82 |
83 | class Answer(models.Model):
84 | user = models.ForeignKey(User, on_delete=models.CASCADE)
85 | choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
86 |
87 | created_at = models.DateTimeField(auto_now_add=True)
88 | updated_at = models.DateTimeField(auto_now=True)
89 |
90 | comments = GenericRelation(Comment, related_query_name="answer")
91 |
92 | def __str__(self):
93 | return self.user.first_name + '-' + self.choice.text
--------------------------------------------------------------------------------
/poll/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework import serializers
2 |
3 | from poll.models import Question, Choice, Tag
4 | from employee.serializers import EmployeeSerializer
5 |
6 |
7 | class ChoiceSerializer(serializers.ModelSerializer):
8 | id = serializers.IntegerField(required=False)
9 |
10 | class Meta:
11 | model = Choice
12 | fields = [
13 | 'id',
14 | 'question',
15 | 'text'
16 | ]
17 | read_only_fields = ('question',)
18 |
19 |
20 | class TagSerializer(serializers.ModelSerializer):
21 | class Meta:
22 | model = Tag
23 | fields = ["name"]
24 |
25 |
26 | class QuestionSerializer(serializers.ModelSerializer):
27 | choices = ChoiceSerializer(many=True)
28 | tags = TagSerializer(many=True)
29 |
30 | class Meta:
31 | model = Question
32 | fields = [
33 | "id",
34 | "title",
35 | "status",
36 | "created_by",
37 | "choices",
38 | "tags"
39 | ]
40 | read_only_fields = ["tags"]
41 |
42 | def create(self, validated_data):
43 | choices = validated_data.pop('choices')
44 | tags = validated_data.pop('tags')
45 | question = Question.objects.create(**validated_data)
46 | for choice in choices:
47 | Choice.objects.create(**choice, question=question)
48 | question.tags.set(tags)
49 | return question
50 |
51 | def update(self, instance, validated_data):
52 | choices = validated_data.pop('choices')
53 | instance.title = validated_data.get("title", instance.title)
54 | instance.save()
55 | keep_choices = []
56 | for choice in choices:
57 | if "id" in choice.keys():
58 | if Choice.objects.filter(id=choice["id"]).exists():
59 | c = Choice.objects.get(id=choice["id"])
60 | c.text = choice.get('text', c.text)
61 | c.save()
62 | keep_choices.append(c.id)
63 | else:
64 | continue
65 | else:
66 | c = Choice.objects.create(**choice, question=instance)
67 | keep_choices.append(c.id)
68 |
69 | for choice in instance.choices:
70 | if choice.id not in keep_choices:
71 | choice.delete()
72 |
73 | return instance
74 |
75 |
76 | class QuestionSearchSerializer(serializers.Serializer):
77 | id = serializers.IntegerField()
78 | title = serializers.CharField()
79 | status = serializers.CharField()
80 | created_at = serializers.DateTimeField()
--------------------------------------------------------------------------------
/poll/templatetags/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aarav-tech/ems/0f43447b8d698e35bae12c0c8a3723e3b1f9c29c/poll/templatetags/__init__.py
--------------------------------------------------------------------------------
/poll/templatetags/poll_extras.py:
--------------------------------------------------------------------------------
1 | from django import template
2 | from poll.models import Question
3 |
4 | register = template.Library()
5 |
6 | def upper(value, n):
7 | """Converts a string into all uppercase"""
8 | return value.upper()[0:n]
9 |
10 | register.filter('upper', upper)
11 |
12 |
13 | @register.simple_tag
14 | def recent_polls(n=5, **kwargs):
15 | """Return recent n polls"""
16 | name = kwargs.get("name", "Argument is not passed")
17 | print(name)
18 | questions = Question.objects.all().order_by('-created_at')
19 | return questions[0:n]
--------------------------------------------------------------------------------
/poll/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/poll/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from poll.views import *
3 |
4 | urlpatterns = [
5 | path('add/', PollView.as_view(), name='poll_add'),
6 | path('/edit/', PollView.as_view(), name='poll_edit'),
7 | path('/delete/', PollView.as_view(), name='poll_delete'),
8 | path('list/', index, name='polls_list'),
9 | path('/details/', details, name="poll_details"),
10 | path('/', vote_poll, name="poll_vote")
11 | ]
--------------------------------------------------------------------------------
/poll/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, reverse, redirect, get_object_or_404
2 | from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse
3 | from django.contrib.auth.decorators import login_required
4 | from django.utils.decorators import method_decorator
5 | from django.views.generic import View
6 | from django.views.decorators.csrf import csrf_exempt
7 | from django.views.generic.edit import CreateView
8 | from django.db.models import Q
9 |
10 | from rest_framework.parsers import JSONParser
11 | from rest_framework.views import APIView
12 | from rest_framework.response import Response
13 | from rest_framework import status
14 | from rest_framework import generics
15 | from rest_framework import mixins
16 | from rest_framework.decorators import action
17 |
18 | from ems.decorators import admin_hr_required, admin_only
19 | from poll.forms import PollForm, ChoiceForm
20 | from poll.models import *
21 | from poll.serializers import QuestionSerializer, ChoiceSerializer, QuestionSearchSerializer
22 | from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
23 | from rest_framework.permissions import IsAuthenticated, IsAdminUser
24 | from rest_framework import viewsets
25 | from rest_framework.decorators import action
26 | from django_filters.rest_framework import DjangoFilterBackend
27 | from django_filters import FilterSet
28 | from django_filters import rest_framework as filters
29 |
30 | class QuestionSearchViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
31 | serializer_class = QuestionSearchSerializer
32 |
33 | def get_queryset(self):
34 | result = QuestionDocument.search()
35 |
36 |
37 | class PollFilter(FilterSet):
38 | tags = filters.CharFilter(method="filter_by_tags")
39 |
40 | class Meta:
41 | model = Question
42 | fields =["tags"]
43 |
44 | def filter_by_tags(self, queryset, name, value):
45 | tag_names = value.strip().split(",")
46 | tags = Tag.objects.filter(name__in=tag_names)
47 | return queryset.filter(tags__in=tags).distinct()
48 |
49 |
50 | class PollViewSet(viewsets.ModelViewSet):
51 | serializer_class = QuestionSerializer
52 | queryset = Question.objects.all()
53 | lookup_field = 'id'
54 | filter_backends = (DjangoFilterBackend,)
55 | filter_class = PollFilter
56 | authentication_classes = (TokenAuthentication,)
57 |
58 |
59 | @action(detail=True, methods=["GET"])
60 | def choices(self, request, id=None):
61 | question = self.get_object()
62 | choices = Choice.objects.filter(question=question)
63 | serializer = ChoiceSerializer(choices, many=True)
64 | return Response(serializer.data, status=200)
65 |
66 | @action(detail=True, methods=["POST"])
67 | def choice(self, request, id=None):
68 | question = self.get_object()
69 | data = request.data
70 | data["question"] = question.id
71 | serializer = ChoiceSerializer(data=data)
72 | if serializer.is_valid():
73 | serializer.save()
74 | return Response(serializer.data, status=201)
75 | return Response(serializer.erros, status=400)
76 |
77 |
78 |
79 | class PollListView(generics.GenericAPIView,
80 | mixins.ListModelMixin,
81 | mixins.CreateModelMixin,
82 | mixins.RetrieveModelMixin,
83 | mixins.UpdateModelMixin,
84 | mixins.DestroyModelMixin):
85 | serializer_class = QuestionSerializer
86 | queryset = Question.objects.all()
87 | lookup_field = 'id'
88 | authentication_classes = [TokenAuthentication, SessionAuthentication, BasicAuthentication]
89 | permission_classes = [IsAuthenticated, IsAdminUser]
90 |
91 |
92 |
93 | def get(self, request, id=None):
94 | if id:
95 | return self.retrieve(request, id)
96 | else:
97 | return self.list(request)
98 |
99 | def post(self, request):
100 | return self.create(request)
101 |
102 | def perform_create(self, serializer):
103 | serializer.save(created_by=self.request.user)
104 |
105 | def put(self, request, id=None):
106 | return self.update(request, id)
107 |
108 | def perform_update(self, serializer):
109 | print(self.request.user)
110 | serializer.save(created_by=self.request.user)
111 |
112 | def delete(self, request, id=None):
113 | return self.destroy(request, id)
114 |
115 |
116 |
117 | class PollAPIView(APIView):
118 | def get(self, request):
119 | questions = Question.objects.all()
120 | serailizer = QuestionSerializer(questions, many=True)
121 | return Response(serailizer.data, status=200)
122 |
123 | def post(self, request):
124 | data = request.data
125 | serializer = QuestionSerializer(data=data)
126 | if serializer.is_valid():
127 | serializer.save()
128 | return Response(serializer.data, status=201)
129 | return Response(serializer.erros, status=400)
130 |
131 | class PollDetailView(APIView):
132 | def get_object(self, id):
133 | try:
134 | return Question.objects.get(id=id)
135 | except Question.DoesNotExist as e:
136 | return Response( {"error": "Given question object not found."}, status=404)
137 |
138 | def get(self, request, id=None):
139 | instance = self.get_object(id)
140 | serailizer = QuestionSerializer(instance)
141 | return Response(serailizer.data)
142 |
143 | def put(self, request, id=None):
144 | data = request.data
145 | instance = self.get_object(id)
146 | serializer = QuestionSerializer(instance, data=data)
147 | if serializer.is_valid():
148 | serializer.save()
149 | return Response(serializer.data, status=200)
150 | return Response(serializer.erros, status=400)
151 |
152 | def delete(self, request, id=None):
153 | instance = self.get_object(id)
154 | instance.delete()
155 | return HttpResponse(status=204)
156 |
157 |
158 | @csrf_exempt
159 | def poll(request):
160 | if request.method == "GET":
161 | questions = Question.objects.all()
162 | serailizer = QuestionSerializer(questions, many=True)
163 | return JsonResponse(serailizer.data, safe=False)
164 |
165 | elif request.method == "POST":
166 | json_parser = JSONParser()
167 | data = json_parser.parse(request)
168 | serializer = QuestionSerializer(data=data)
169 | if serializer.is_valid():
170 | serializer.save()
171 | return JsonResponse(serializer.data, status=201)
172 | return JsonResponse(serializer.erros, status=400)
173 |
174 |
175 | @csrf_exempt
176 | def poll_details(request, id):
177 | try:
178 | instance = Question.objects.get(id=id)
179 | except Question.DoesNotExist as e:
180 | return JsonResponse( {"error": "Given question object not found."}, status=404)
181 |
182 | if request.method == "GET":
183 | serailizer = QuestionSerializer(instance)
184 | return JsonResponse(serailizer.data)
185 |
186 | elif request.method == "PUT":
187 | json_parser = JSONParser()
188 | data = json_parser.parse(request)
189 | serializer = QuestionSerializer(instance, data=data)
190 | if serializer.is_valid():
191 | serializer.save()
192 | return JsonResponse(serializer.data, status=200)
193 | return JsonResponse(serializer.erros, status=400)
194 |
195 | elif request.method == "DELETE":
196 | instance.delete()
197 | return HttpResponse(status=204)
198 |
199 |
200 | class PollView(View):
201 | decorators = [login_required, admin_hr_required]
202 |
203 | @method_decorator(decorators)
204 | def get(self, request, id=None):
205 | if id:
206 | question = get_object_or_404(Question, id=id)
207 | poll_form = PollForm(instance=question)
208 | choices = question.choice_set.all()
209 | choice_forms = [ChoiceForm(prefix=str(
210 | choice.id), instance=choice) for choice in choices]
211 | template = 'polls/edit_poll.html'
212 | else:
213 | poll_form = PollForm(instance=Question())
214 | choice_forms = [ChoiceForm(prefix=str(
215 | x), instance=Choice()) for x in range(3)]
216 | template = 'polls/new_poll.html'
217 | context = {'poll_form': poll_form, 'choice_forms': choice_forms}
218 | return render(request, template, context)
219 |
220 | @method_decorator(decorators)
221 | def post(self, request, id=None):
222 | context = {}
223 | if id:
224 | return self.put(request, id)
225 | poll_form = PollForm(request.POST, instance=Question())
226 | choice_forms = [ChoiceForm(request.POST, prefix=str(
227 | x), instance=Choice()) for x in range(0, 3)]
228 | if poll_form.is_valid() and all([cf.is_valid() for cf in choice_forms]):
229 | new_poll = poll_form.save(commit=False)
230 | new_poll.created_by = request.user
231 | new_poll.save()
232 | for cf in choice_forms:
233 | new_choice = cf.save(commit=False)
234 | new_choice.question = new_poll
235 | new_choice.save()
236 | return HttpResponseRedirect('/poll/list/')
237 | context = {'poll_form': poll_form, 'choice_forms': choice_forms}
238 | return render(request, 'polls/new_poll.html', context)
239 |
240 | @method_decorator(decorators)
241 | def put(self, request, id=None):
242 | context = {}
243 | question = get_object_or_404(Question, id=id)
244 | poll_form = PollForm(request.POST, instance=question)
245 | choice_forms = [ChoiceForm(request.POST, prefix=str(
246 | choice.id), instance=choice) for choice in question.choice_set.all()]
247 | if poll_form.is_valid() and all([cf.is_valid() for cf in choice_forms]):
248 | new_poll = poll_form.save(commit=False)
249 | new_poll.created_by = request.user
250 | new_poll.save()
251 | for cf in choice_forms:
252 | new_choice = cf.save(commit=False)
253 | new_choice.question = new_poll
254 | new_choice.save()
255 | return redirect('polls_list')
256 | context = {'poll_form': poll_form, 'choice_forms': choice_forms}
257 | return render(request, 'polls/edit_poll.html', context)
258 |
259 | @method_decorator(decorators)
260 | def delete(self, request, id=None):
261 | question = get_object_or_404(Question)
262 | question.delete()
263 | return redirect('polls_list')
264 |
265 |
266 | @login_required(login_url="/login/")
267 | def index(request):
268 | context = {}
269 | questions = Question.objects.all()
270 | context['title'] = 'polls'
271 | context['questions'] = questions
272 | return render(request, 'polls/index.html', context)
273 |
274 |
275 | @login_required(login_url="/login/")
276 | def details(request, id=None):
277 | context = {}
278 | try:
279 | question = Question.objects.get(id=id)
280 | except:
281 | raise Http404
282 | context['question'] = question
283 | return render(request, 'polls/details.html', context)
284 |
285 |
286 | @login_required(login_url="/login/")
287 | def vote_poll(request, id=None):
288 | context = {}
289 | try:
290 | question = Question.objects.get(id=id)
291 | except:
292 | raise Http404
293 | context["question"] = question
294 |
295 | if request.method == "POST":
296 | user_id = 1
297 | print(request.POST)
298 | data = request.POST
299 | ret = Answer.objects.create(user_id=user_id, choice_id=data['choice'])
300 | if ret:
301 | return HttpResponseRedirect(reverse('poll_details', args=[question.id]))
302 | else:
303 | context["error"] = "Your vote is not done successfully"
304 | return render(request, 'polls/poll.html', context)
305 | else:
306 | return render(request, 'polls/poll.html', context)
307 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | django==2.0
2 | djangorestframework==3.8.2
3 | django-extensions
4 | pillow
5 | django-filter==1.1.0
6 | whoosh
7 | django-haystack
8 | django-elasticsearch-dsl
9 | django-rest-swagger
10 |
--------------------------------------------------------------------------------