Skip to content

Commit b86ec2a

Browse files
committed
Initial commit
0 parents  commit b86ec2a

21 files changed

+653
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/venv/
2+
.idea

api/__init__.py

Whitespace-only changes.

api/admin.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.contrib import admin
2+
3+
from api.models import User, Department
4+
5+
# Register your models here.
6+
7+
admin.site.register(User)
8+
admin.site.register(Department)

api/apps.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ApiConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'api'

api/migrations/0001_initial.py

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Generated by Django 4.2.3 on 2023-07-28 06:53
2+
3+
import django.contrib.auth.models
4+
import django.contrib.auth.validators
5+
import django.utils.timezone
6+
from django.conf import settings
7+
from django.db import migrations, models
8+
9+
10+
class Migration(migrations.Migration):
11+
initial = True
12+
13+
dependencies = [
14+
('auth', '0012_alter_user_first_name_max_length'),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='User',
20+
fields=[
21+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
23+
('is_superuser', models.BooleanField(default=False,
24+
help_text='Designates that this user has all permissions without explicitly assigning them.',
25+
verbose_name='superuser status')),
26+
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'},
27+
help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
28+
max_length=150, unique=True,
29+
validators=[django.contrib.auth.validators.UnicodeUsernameValidator()],
30+
verbose_name='username')),
31+
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
32+
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
33+
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
34+
('is_staff', models.BooleanField(default=False,
35+
help_text='Designates whether the user can log into this admin site.',
36+
verbose_name='staff status')),
37+
('is_active', models.BooleanField(default=True,
38+
help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.',
39+
verbose_name='active')),
40+
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
41+
('role', models.CharField(choices=[('patient', 'Patient'), ('doctor', 'Doctor')], max_length=10)),
42+
('password', models.CharField(max_length=255)),
43+
],
44+
options={
45+
'verbose_name': 'user',
46+
'verbose_name_plural': 'users',
47+
'abstract': False,
48+
},
49+
managers=[
50+
('objects', django.contrib.auth.models.UserManager()),
51+
],
52+
),
53+
migrations.CreateModel(
54+
name='Department',
55+
fields=[
56+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
57+
('name', models.CharField(max_length=50)),
58+
('diagnostics', models.CharField(max_length=100)),
59+
('location', models.CharField(max_length=100)),
60+
('specialization', models.CharField(max_length=20)),
61+
],
62+
),
63+
migrations.CreateModel(
64+
name='PatientReport',
65+
fields=[
66+
('record_id', models.BigAutoField(primary_key=True, serialize=False)),
67+
('created', models.DateTimeField(auto_now_add=True)),
68+
('diagnostics', models.TextField()),
69+
('observations', models.TextField()),
70+
('treatments', models.TextField()),
71+
('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.department')),
72+
(
73+
'patient',
74+
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
75+
],
76+
),
77+
migrations.AddField(
78+
model_name='user',
79+
name='department',
80+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
81+
to='api.department'),
82+
),
83+
migrations.AddField(
84+
model_name='user',
85+
name='groups',
86+
field=models.ManyToManyField(blank=True,
87+
help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
88+
related_name='user_set', related_query_name='user', to='auth.group',
89+
verbose_name='groups'),
90+
),
91+
migrations.AddField(
92+
model_name='user',
93+
name='user_permissions',
94+
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.',
95+
related_name='user_set', related_query_name='user', to='auth.permission',
96+
verbose_name='user permissions'),
97+
),
98+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.3 on 2023-07-28 06:59
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
dependencies = [
9+
('api', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='user',
15+
name='department',
16+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.department'),
17+
),
18+
]

api/migrations/__init__.py

Whitespace-only changes.

api/models.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from django.contrib.auth.models import AbstractUser, UserManager
2+
from django.db import models
3+
4+
5+
class Department(models.Model):
6+
name = models.CharField(max_length=50)
7+
diagnostics = models.CharField(max_length=100)
8+
location = models.CharField(max_length=100)
9+
specialization = models.CharField(max_length=20)
10+
11+
def __str__(self):
12+
return self.name
13+
14+
15+
class DoctorManager(models.Manager):
16+
def get_queryset(self):
17+
return super().get_queryset().filter(role=User.Role.DOCTOR)
18+
19+
20+
class PatientManager(models.Manager):
21+
def get_queryset(self):
22+
return super().get_queryset().filter(role=User.Role.PATIENT)
23+
24+
25+
class User(AbstractUser):
26+
class Role(models.TextChoices):
27+
PATIENT = 'patient', 'Patient'
28+
DOCTOR = 'doctor', 'Doctor'
29+
30+
role = models.CharField(max_length=10,
31+
choices=Role.choices
32+
)
33+
password = models.CharField(max_length=255)
34+
department = models.ForeignKey(Department, on_delete=models.CASCADE)
35+
36+
objects = UserManager()
37+
doctors = DoctorManager()
38+
patients = PatientManager()
39+
40+
41+
class PatientReport(models.Model):
42+
record_id = models.BigAutoField(primary_key=True)
43+
patient = models.ForeignKey(User, on_delete=models.CASCADE)
44+
created = models.DateTimeField(auto_now_add=True)
45+
department = models.ForeignKey(Department, on_delete=models.CASCADE)
46+
diagnostics = models.TextField()
47+
observations = models.TextField()
48+
treatments = models.TextField()
49+
50+
def __str__(self):
51+
return f'{self.patient.username}\'s report'

api/permissions.py

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from rest_framework.permissions import BasePermission
2+
from rest_framework.response import Response
3+
4+
from api.models import User
5+
6+
7+
class DoctorOnly(BasePermission):
8+
def has_permission(self, request, view):
9+
if request.user.is_authenticated and (request.user.role == User.Role.DOCTOR or request.user.is_superuser):
10+
return True
11+
return False
12+
13+
14+
class PatientsOnly(BasePermission):
15+
def has_permission(self, request, view):
16+
if request.user.is_authenticated and (request.user.role == User.Role.DOCTOR or request.user.is_superuser):
17+
return True
18+
return False
19+
20+
21+
class DoctorSpecific(BasePermission):
22+
def has_object_permission(self, request, view, obj):
23+
if request.user.is_authenticated and (obj == request.user or request.user.is_superuser):
24+
return True
25+
return False
26+
27+
28+
class PatientSpecific(BasePermission):
29+
def has_object_permission(self, request, view, obj):
30+
if request.user.is_authenticated and (obj == request.user or request.user.is_superuser):
31+
return True
32+
return False
33+
34+
35+
class DoctorsPatientSpecific(BasePermission):
36+
def has_object_permission(self, request, view, obj):
37+
if request.user.is_authenticated and (
38+
(obj.patient == request.user or request.user.is_superuser) or request.user.role == User.Role.DOCTOR):
39+
return True
40+
return False
41+
42+
43+
class DepartmentDoctor(BasePermission):
44+
def has_permission(self, request, view):
45+
if not view.get_queryset().first():
46+
return Response()
47+
if request.user.is_authenticated and ((request.user in view.get_queryset()) or request.user.is_superuser):
48+
return True
49+
return False
50+
51+
52+
class DepartmentPatient(BasePermission):
53+
def has_permission(self, request, view):
54+
if view.get_queryset().first():
55+
return Response({'msg': 'Department is empty', })
56+
if request.user.is_authenticated and (
57+
request.user.department == view.get_queryset().first().department or request.user.is_superuser):
58+
return True
59+
return False

api/serializers.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from rest_framework import serializers
2+
3+
from .models import User, Department, PatientReport
4+
5+
6+
class UserSerializer(serializers.ModelSerializer):
7+
class Meta:
8+
model = User
9+
fields = ['id', 'username', 'password', 'role', 'department']
10+
extra_kwargs = {
11+
'password': {
12+
'write_only': True,
13+
},
14+
}
15+
16+
def create(self, validated_data):
17+
password = validated_data.pop('password', None)
18+
instance = self.Meta.model(**validated_data)
19+
if password is not None:
20+
instance.set_password(password)
21+
instance.save()
22+
return instance
23+
24+
25+
class UserSerializerModified(serializers.ModelSerializer):
26+
class Meta:
27+
model = User
28+
fields = ['id', 'username', 'password', 'department']
29+
extra_kwargs = {
30+
'password': {
31+
'write_only': True,
32+
},
33+
34+
}
35+
36+
def create(self, validated_data):
37+
password = validated_data.pop('password', None)
38+
instance = self.Meta.model(**validated_data)
39+
if password is not None:
40+
instance.set_password(password)
41+
instance.save()
42+
return instance
43+
44+
45+
class DepartmentSerializer(serializers.ModelSerializer):
46+
class Meta:
47+
model = Department
48+
fields = ['name', 'specialization', 'diagnostics', 'location']
49+
50+
51+
class PatientReportSerializer(serializers.ModelSerializer):
52+
class Meta:
53+
model = PatientReport
54+
fields = ['record_id', 'patient', 'department', 'created', 'diagnostics', 'observations', 'treatments']
55+
56+
def to_representation(self, instance):
57+
rep = super(PatientReportSerializer, self).to_representation(instance)
58+
rep['student'] = instance.student.username
59+
rep['department'] = instance.department.name
60+
return rep
61+
62+
def validate(self, attrs):
63+
print(attrs)
64+
student = attrs.get('student')
65+
if student.role != User.Role.PATIENT:
66+
raise serializers.ValidationError("Report can be created for students only")
67+
return attrs

api/tests.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Create your tests here.

api/urls.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from django.urls import path
2+
from rest_framework_simplejwt.views import TokenRefreshView, TokenObtainPairView
3+
4+
from api.views import RegisterView, DepartmentPatientView, DepartmentDoctorView, DepartmentDetailView, \
5+
DoctorDetailView, DepartmentListView, DoctorListView, PatientReportDetailView, PatientListView, \
6+
PatientReportListView, PatientDetailView
7+
8+
urlpatterns = [
9+
10+
path('login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
11+
path('login/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
12+
path('register/', RegisterView.as_view(), name="sign_up"),
13+
path('doctors/', DoctorListView.as_view()),
14+
path('doctors/<int:pk>/', DoctorDetailView.as_view()),
15+
path('patients/<int:pk>/', PatientDetailView.as_view()),
16+
path('patients/', PatientListView.as_view()),
17+
path('departments/', DepartmentListView.as_view()),
18+
path('departments/<int:pk>/', DepartmentDetailView.as_view()),
19+
path('department/<int:pk>/teachers/', DepartmentDoctorView.as_view()),
20+
path('department/<int:pk>/students/', DepartmentPatientView.as_view()),
21+
path('patient_record/', PatientReportListView.as_view()),
22+
path('patient_record/<int:pk>/', PatientReportDetailView.as_view()),
23+
24+
]

0 commit comments

Comments
 (0)