begin api
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/db.sqlite3
|
||||||
57
education/filters.py
Normal file
57
education/filters.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import django_filters
|
||||||
|
from .models import AcademicYear, Department, DepartmentHead, Specialty, Group, Student
|
||||||
|
|
||||||
|
class AcademicYearFilter(django_filters.FilterSet):
|
||||||
|
year = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = AcademicYear
|
||||||
|
fields = ["year"]
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentFilter(django_filters.FilterSet):
|
||||||
|
name = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Department
|
||||||
|
fields = ["name"]
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentHeadFilter(django_filters.FilterSet):
|
||||||
|
department_name = django_filters.CharFilter(field_name="department__name", lookup_expr="icontains")
|
||||||
|
head_name = django_filters.CharFilter(field_name="head__first_name", lookup_expr="icontains")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = DepartmentHead
|
||||||
|
fields = ["department_name", "head_name"]
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialtyFilter(django_filters.FilterSet):
|
||||||
|
name = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
code = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
department_name = django_filters.CharFilter(field_name="department__name", lookup_expr="icontains")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Specialty
|
||||||
|
fields = ["name", "code", "department_name"]
|
||||||
|
|
||||||
|
|
||||||
|
class GroupFilter(django_filters.FilterSet):
|
||||||
|
name = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
curator_name = django_filters.CharFilter(field_name="curator__first_name", lookup_expr="icontains")
|
||||||
|
specialty_name = django_filters.CharFilter(field_name="specialty__name", lookup_expr="icontains")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Group
|
||||||
|
fields = ["name", "curator_name", "specialty_name"]
|
||||||
|
|
||||||
|
|
||||||
|
class StudentFilter(django_filters.FilterSet):
|
||||||
|
first_name = django_filters.CharFilter(field_name="account__first_name", lookup_expr="icontains")
|
||||||
|
last_name = django_filters.CharFilter(field_name="account__last_name", lookup_expr="icontains")
|
||||||
|
group_name = django_filters.CharFilter(field_name="group__name", lookup_expr="icontains")
|
||||||
|
specialty_name = django_filters.CharFilter(field_name="group__specialty__name", lookup_expr="icontains")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Student
|
||||||
|
fields = ["first_name", "last_name", "group_name", "specialty_name"]
|
||||||
75
education/serializers.py
Normal file
75
education/serializers.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from .models import AcademicYear, Department, DepartmentHead, Specialty, Group, Student
|
||||||
|
|
||||||
|
class AcademicYearSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = AcademicYear
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Department
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentHeadSerializer(serializers.ModelSerializer):
|
||||||
|
head_name = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = DepartmentHead
|
||||||
|
fields = ["id", "department", "head", "head_name"]
|
||||||
|
|
||||||
|
def get_head_name(self, obj):
|
||||||
|
return f"{obj.head.first_name} {obj.head.last_name}"
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialtySerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Specialty
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class GroupSerializer(serializers.ModelSerializer):
|
||||||
|
curator_name = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Group
|
||||||
|
fields = ["id", "name", "curator", "specialty", "curator_name"]
|
||||||
|
|
||||||
|
def get_curator_name(self, obj):
|
||||||
|
if obj.curator:
|
||||||
|
return f"{obj.curator.first_name} {obj.curator.last_name}"
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class StudentSerializer(serializers.ModelSerializer):
|
||||||
|
first_name = serializers.CharField(source="account.first_name")
|
||||||
|
last_name = serializers.CharField(source="account.last_name")
|
||||||
|
middle_name = serializers.CharField(source="account.middle_name")
|
||||||
|
phone = serializers.CharField(source="account.phone")
|
||||||
|
email = serializers.CharField(source="account.email")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Student
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
"group",
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
"middle_name",
|
||||||
|
"phone",
|
||||||
|
"email",
|
||||||
|
]
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
account_data = validated_data.pop("account", {})
|
||||||
|
instance.account.first_name = account_data.get("first_name", instance.account.first_name)
|
||||||
|
instance.account.last_name = account_data.get("last_name", instance.account.last_name)
|
||||||
|
instance.account.middle_name = account_data.get("middle_name", instance.account.middle_name)
|
||||||
|
instance.account.phone = account_data.get("phone", instance.account.phone)
|
||||||
|
instance.account.email = account_data.get("email", instance.account.email)
|
||||||
|
instance.account.save()
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
|
|
||||||
22
education/urls.py
Normal file
22
education/urls.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from django.urls import path, include
|
||||||
|
from rest_framework.routers import DefaultRouter
|
||||||
|
from .views import (
|
||||||
|
AcademicYearViewSet,
|
||||||
|
DepartmentViewSet,
|
||||||
|
DepartmentHeadViewSet,
|
||||||
|
SpecialtyViewSet,
|
||||||
|
GroupViewSet,
|
||||||
|
StudentViewSet,
|
||||||
|
)
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register(r"academic-years", AcademicYearViewSet, basename="academic-year")
|
||||||
|
router.register(r"departments", DepartmentViewSet, basename="department")
|
||||||
|
router.register(r"department-heads", DepartmentHeadViewSet, basename="department-head")
|
||||||
|
router.register(r"specialties", SpecialtyViewSet, basename="specialty")
|
||||||
|
router.register(r"groups", GroupViewSet, basename="group")
|
||||||
|
router.register(r"students", StudentViewSet, basename="student")
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", include(router.urls)),
|
||||||
|
]
|
||||||
@@ -1,3 +1,73 @@
|
|||||||
from django.shortcuts import render
|
from rest_framework import viewsets
|
||||||
|
from rest_framework.filters import SearchFilter, OrderingFilter
|
||||||
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
|
from .models import AcademicYear, Department, DepartmentHead, Specialty, Group, Student
|
||||||
|
from .serializers import (
|
||||||
|
AcademicYearSerializer,
|
||||||
|
DepartmentSerializer,
|
||||||
|
DepartmentHeadSerializer,
|
||||||
|
SpecialtySerializer,
|
||||||
|
GroupSerializer,
|
||||||
|
StudentSerializer,
|
||||||
|
)
|
||||||
|
from .filters import (
|
||||||
|
AcademicYearFilter,
|
||||||
|
DepartmentFilter,
|
||||||
|
DepartmentHeadFilter,
|
||||||
|
SpecialtyFilter,
|
||||||
|
GroupFilter,
|
||||||
|
StudentFilter,
|
||||||
|
)
|
||||||
|
|
||||||
# Create your views here.
|
class AcademicYearViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = AcademicYear.objects.all()
|
||||||
|
serializer_class = AcademicYearSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = AcademicYearFilter
|
||||||
|
search_fields = ["year"]
|
||||||
|
ordering_fields = ["year"]
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Department.objects.all()
|
||||||
|
serializer_class = DepartmentSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = DepartmentFilter
|
||||||
|
search_fields = ["name"]
|
||||||
|
ordering_fields = ["name"]
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentHeadViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = DepartmentHead.objects.all()
|
||||||
|
serializer_class = DepartmentHeadSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = DepartmentHeadFilter
|
||||||
|
search_fields = ["department__name", "head__first_name"]
|
||||||
|
ordering_fields = ["department", "head"]
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialtyViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Specialty.objects.all()
|
||||||
|
serializer_class = SpecialtySerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = SpecialtyFilter
|
||||||
|
search_fields = ["name", "code", "department__name"]
|
||||||
|
ordering_fields = ["name", "code"]
|
||||||
|
|
||||||
|
|
||||||
|
class GroupViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Group.objects.all()
|
||||||
|
serializer_class = GroupSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = GroupFilter
|
||||||
|
search_fields = ["name", "curator__first_name", "specialty__name"]
|
||||||
|
ordering_fields = ["name", "specialty"]
|
||||||
|
|
||||||
|
|
||||||
|
class StudentViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Student.objects.all()
|
||||||
|
serializer_class = StudentSerializer
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = StudentFilter
|
||||||
|
search_fields = ["account__first_name", "account__last_name", "group__name"]
|
||||||
|
ordering_fields = ["group", "account__last_name"]
|
||||||
@@ -1 +1,11 @@
|
|||||||
django~=4.2.21
|
django~=4.2.21
|
||||||
|
django-cors-headers
|
||||||
|
djangorestframework
|
||||||
|
drf-yasg
|
||||||
|
Pillow
|
||||||
|
requests
|
||||||
|
django-autoslug
|
||||||
|
transliterate
|
||||||
|
pytest-django
|
||||||
|
pytest
|
||||||
|
django-filter
|
||||||
@@ -39,6 +39,10 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'corsheaders',
|
||||||
|
'rest_framework',
|
||||||
|
"django_filters",
|
||||||
|
'drf_yasg',
|
||||||
"core.apps.CoreConfig",
|
"core.apps.CoreConfig",
|
||||||
'users.apps.UsersConfig',
|
'users.apps.UsersConfig',
|
||||||
"employees.apps.EmployeesConfig",
|
"employees.apps.EmployeesConfig",
|
||||||
@@ -51,6 +55,7 @@ INSTALLED_APPS = [
|
|||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'corsheaders.middleware.CorsMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
@@ -149,3 +154,21 @@ MEDIA_ROOT = BASE_DIR / 'media'
|
|||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
AUTH_USER_MODEL = "users.Account"
|
AUTH_USER_MODEL = "users.Account"
|
||||||
|
|
||||||
|
|
||||||
|
CORS_ORIGIN_WHITELIST = ['http://localhost:8000',
|
||||||
|
'http://localhost:3000']
|
||||||
|
CSRF_TRUSTED_ORIGINS = ['http://localhost:8000',
|
||||||
|
'http://localhost:3000']
|
||||||
|
|
||||||
|
CORS_ALLOW_CREDENTIALS = True
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning",
|
||||||
|
"DEFAULT_VERSION": "v1",
|
||||||
|
|
||||||
|
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
|
||||||
|
"PAGE_SIZE": 10,
|
||||||
|
|
||||||
|
"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,9 +14,37 @@ Including another URLconf
|
|||||||
1. Import the include() function: from django.urls import include, path
|
1. Import the include() function: from django.urls import include, path
|
||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import path, include
|
||||||
|
from drf_yasg import openapi
|
||||||
|
from drf_yasg.views import get_schema_view
|
||||||
|
from rest_framework import permissions
|
||||||
|
|
||||||
|
schema_view = get_schema_view(
|
||||||
|
openapi.Info(
|
||||||
|
title="ProFi API",
|
||||||
|
default_version='v1',
|
||||||
|
description="API for ProFi (v1)",
|
||||||
|
contact=openapi.Contact(email="support@novelplus.ru"),
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
public=True,
|
||||||
|
permission_classes=[permissions.AllowAny],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
]
|
path('api/v1/education/', include("education.urls")),
|
||||||
|
|
||||||
|
path('docs/swagger<format>/', schema_view.without_ui(cache_timeout=0), name='schema-json'),
|
||||||
|
path('docs/swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||||
|
path('docs/redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
|
||||||
|
|
||||||
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
|||||||
Reference in New Issue
Block a user