Skip to content

Commit

Permalink
Add some api improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
1yunker committed Oct 21, 2023
1 parent 93d7697 commit 39443e5
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 60 deletions.
27 changes: 25 additions & 2 deletions backend/api/filters.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import django_filters
from django_filters.rest_framework import FilterSet, filters
from taggit.models import Tag

from content.models import City, Skills
from projects.models import Project
from projects.models import Category, Project

# from django.core.validators import RegexValidator
# from django.db.models import Q


# from django.db.models import Q
class ProjectCategoryFilter(FilterSet):
"""
Класс для фильтрации городов по имени.
"""

name = filters.CharFilter(field_name='name', lookup_expr='icontains')

class Meta:
model = Category
fields = ('name',)


class CityFilter(FilterSet):
Expand All @@ -34,6 +45,18 @@ class Meta:
fields = ('name',)


class TagFilter(FilterSet):
"""
Класс для фильтрации тегов по имени.
"""

name = filters.CharFilter(field_name='name', lookup_expr='icontains')

class Meta:
model = Tag
fields = ('name',)


class ProjectFilter(FilterSet):
"""
Класс для фильтрации проектов по имени, статусу, категории, организации.
Expand Down
127 changes: 75 additions & 52 deletions backend/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import django.contrib.auth.password_validation as validators
from django.core import exceptions
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.utils import timezone
from djoser.serializers import UserCreateSerializer, UserSerializer
from rest_framework import serializers
from taggit.models import Tag

from content.models import (
City,
Expand All @@ -13,6 +14,7 @@
Valuation,
)
from projects.models import (
Category,
Organization,
Project,
Volunteer,
Expand Down Expand Up @@ -56,7 +58,7 @@ def get_projects_count(self, obj):
return Project.objects.count()

def get_volunteers_count(self, obj):
return User.objects.filter(role='volunteer').count()
return Volunteer.objects.count()

def get_organizers_count(self, obj):
return User.objects.filter(role='organizer').count()
Expand Down Expand Up @@ -109,10 +111,32 @@ class Meta:
fields = ('name', 'phone', 'email', 'text')


class CitySerializer(serializers.ModelSerializer):
"""
Сериализатор для отображения городов.
"""

class Meta:
model = City
fields = ('id', 'name')


class ProjectCategorySerializer(serializers.ModelSerializer):
"""
Сериализатор для отображения категорий проекта.
"""

class Meta:
model = Category
exclude = ('description',)


class ProjectSerializer(serializers.ModelSerializer):
"""
Сериализатор для Project.
"""
category = ProjectCategorySerializer()
city = CitySerializer()

def validate_dates(self, start, end, application):
"""
Expand Down Expand Up @@ -196,16 +220,6 @@ class Meta:
)


class CitySerializer(serializers.ModelSerializer):
"""
Сериализатор для отображения городов.
"""

class Meta:
model = City
fields = ('id', 'name')


class SkillsSerializer(serializers.ModelSerializer):
"""
Сериализатор для отображения навыков.
Expand All @@ -216,47 +230,14 @@ class Meta:
fields = ('id', 'name')


class UserSerializer(serializers.ModelSerializer):
"""
Сериализатор для получения пользователя.
"""

class Meta:
model = User
fields = (
'id',
'first_name',
'second_name',
'last_name',
'email',
)


class UserCreateSerializer(serializers.ModelSerializer):
class TagSerializer(serializers.ModelSerializer):
"""
Сериализатор для создания пользователя.
Сериализатор для отображения тегов.
"""

def validate(self, data):
password = data.get('password')
errors = dict()
try:
validators.validate_password(password=password)
except exceptions.ValidationError as e:
errors['password'] = list(e.messages)
if errors:
raise serializers.ValidationError(errors)
return super(UserCreateSerializer, self).validate(data)

class Meta:
model = User
fields = (
'first_name',
'second_name',
'last_name',
'email',
'password',
)
model = Tag
fields = ('name', 'slug',)


class VolunteerGetSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -299,14 +280,56 @@ def create(self, validated_data):

return volunteer

# @transaction.atomic
# def update(self, instance, validated_data):
# skills = validated_data.pop('skills')
# VolunteerSkills.objects.filter(volunteer=instance).delete()
# self.create_skills(skills, instance)

# user_data = validated_data.pop('user')
# user = User.objects.get(email=user_data.get('email'))
# user.first_name = user_data.get('first_name')
# user.second_name = user_data.get('second_name')
# user.last_name = user_data.get('last_name')
# user.save()

# for attr, value in validated_data.items():
# if hasattr(instance, attr):
# setattr(instance, attr, value)

# instance.save()
# return instance

class Meta:
model = Volunteer
exclude = ('id',)


class VolunteerUpdateSerializer(serializers.ModelSerializer):
"""
Сериализатор для редактирования волонтера.
"""

user = UserSerializer()
skills = serializers.PrimaryKeyRelatedField(
queryset=Skills.objects.all(), many=True
)

def create_skills(self, skills, volunteer):
data = []
for skill in skills:
data.append(VolunteerSkills(volunteer=volunteer, skill=skill))
VolunteerSkills.objects.bulk_create(data)

@transaction.atomic
def update(self, instance, validated_data):
skills = validated_data.pop('skills')
VolunteerSkills.objects.filter(volunteer=instance).delete()
self.create_skills(skills, instance)

user_data = validated_data.pop('user')
user = User.objects.get(email=user_data.get('email'))
email = user_data.get('email')
user = get_object_or_404(User, email=email)
user.first_name = user_data.get('first_name')
user.second_name = user_data.get('second_name')
user.last_name = user_data.get('last_name')
Expand Down Expand Up @@ -376,7 +399,7 @@ class Meta:

class ProjectParticipantSerializer(serializers.Serializer):
"""
Сериализатор для списока участников.
Сериализатор для списка участников.
"""

class Meta:
Expand Down
13 changes: 12 additions & 1 deletion backend/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.urls import include, path
from djoser.views import UserViewSet
from rest_framework.routers import DefaultRouter

from api.views import (
Expand All @@ -7,26 +8,36 @@
NewsViewSet,
OrganizationViewSet,
PlatformAboutView,
ProjectCategoryViewSet,
ProjectViewSet,
SearchListView,
SkillsViewSet,
TagViewSet,
VolunteerViewSet,
VolunteerProfileView,
)

router = DefaultRouter()
router.register(r'news', NewsViewSet, basename='news')
router.register(r'projects', ProjectViewSet, basename='projects')
router.register(r'project_categories', ProjectCategoryViewSet)
router.register(r'volunteers', VolunteerViewSet, basename='volunteers')
router.register(
r'organizations', OrganizationViewSet, basename='organizations'
)
router.register(r'cities', CityViewSet)
router.register(r'skills', SkillsViewSet)
router.register(r'tags', TagViewSet)

urlpatterns = [
path('', include(router.urls)),
# path('', include('djoser.urls')), # это вроде можно убрать
path('auth/me/', UserViewSet.as_view({'get': 'me'}),),
path('auth/change_password/',
UserViewSet.as_view({'post': 'set_password'}),
name='set_password'),
path('auth/reset_password/',
UserViewSet.as_view({'post': 'reset_password'}),
name='password_reset'),
path('auth/', include('djoser.urls.authtoken')),
path('platform_about/', PlatformAboutView.as_view()),
path('feedback/', FeedbackCreateView.as_view()),
Expand Down
33 changes: 30 additions & 3 deletions backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from rest_framework import filters, generics, status, viewsets
from rest_framework.permissions import SAFE_METHODS
from rest_framework.response import Response
from taggit.models import Tag
# from taggit.serializers import TaggitSerializer

from backend.settings import VALUATIONS_ON_PAGE_ABOUT_US
from content.models import (
Expand All @@ -12,9 +14,15 @@
Skills,
Valuation,
)
from projects.models import Organization, Project, Volunteer

from .filters import CityFilter, ProjectFilter, SkillsFilter
from projects.models import Category, Organization, Project, Volunteer

from .filters import (
CityFilter,
ProjectCategoryFilter,
ProjectFilter,
SkillsFilter,
TagFilter,
)
from .permissions import IsOrganizerPermission
from .serializers import (
CitySerializer,
Expand All @@ -24,10 +32,13 @@
OrganizationGetSerializer,
PlatformAboutSerializer,
PreviewNewsSerializer,
ProjectCategorySerializer,
ProjectSerializer,
SkillsSerializer,
TagSerializer,
VolunteerCreateSerializer,
VolunteerGetSerializer,
VolunteerUpdateSerializer,
VolunteerProfileSerializer,
)

Expand Down Expand Up @@ -112,6 +123,8 @@ class VolunteerViewSet(viewsets.ModelViewSet):
def get_serializer_class(self):
if self.request.method in SAFE_METHODS:
return VolunteerGetSerializer
if self.request.method in ('PUT', 'PATCH'):
return VolunteerUpdateSerializer
return VolunteerCreateSerializer


Expand All @@ -138,6 +151,20 @@ class SkillsViewSet(viewsets.ReadOnlyModelViewSet):
filterset_class = SkillsFilter


class TagViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Tag.objects.all()
serializer_class = TagSerializer
pagination_class = None
filterset_class = TagFilter


class ProjectCategoryViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Category.objects.all()
serializer_class = ProjectCategorySerializer
pagination_class = None
filterset_class = ProjectCategoryFilter


class SearchListView(generics.ListAPIView):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Migration(migrations.Migration):
name='ProjectIncomes',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status_incomes', models.CharField(blank=True, choices=[('application_submitted', 'Одобрено'), ('rejected', 'На рассмотрении'), ('accepted', 'Принята')], default=None, null=True, verbose_name='Статус заявки волонтера')),
('status_incomes', models.CharField(blank=True, choices=[('application_submitted', 'Одобрено'), ('rejected', 'На рассмотрении'), ('accepted', 'Принята')], default=None, max_length=100, null=True, verbose_name='Статус заявки волонтера')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_incomes', to='projects.project', verbose_name='Проект')),
('volunteer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_incomes', to='projects.volunteer', verbose_name='Волонтер')),
],
Expand Down
Loading

0 comments on commit 39443e5

Please sign in to comment.