From 7a88e39b96afb9ee4eaa1b3587ded165cd59e38c Mon Sep 17 00:00:00 2001 From: komoliddin Date: Thu, 23 Apr 2026 18:04:09 +0500 Subject: [PATCH 1/8] Enhance Certificate model and serializer to support file uploads and URL generation --- core/apps/evaluation/models/certificate.py | 16 +++++++++++++--- .../serializers/certificate/certificate.py | 17 +++++++++++++++-- core/apps/evaluation/views/certificate.py | 3 +++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/core/apps/evaluation/models/certificate.py b/core/apps/evaluation/models/certificate.py index 5b8233c..4089da4 100644 --- a/core/apps/evaluation/models/certificate.py +++ b/core/apps/evaluation/models/certificate.py @@ -1,11 +1,21 @@ from django.db import models from django_core.models import AbstractBaseModel -from model_bakery import baker from django.utils.translation import gettext_lazy as _ +from model_bakery import baker + class CertificateModel(AbstractBaseModel): - title = models.CharField(verbose_name=_("title"), max_length=255, blank=False, null=False) - file_url = models.URLField(verbose_name=_("file url"), max_length=255, blank=False, null=False) + title = models.CharField( + verbose_name=_("title"), + max_length=255 + ) + + file = models.FileField( + verbose_name=_("file"), + upload_to="certificates/", + blank=True, + null=True + ) def __str__(self): return self.title diff --git a/core/apps/evaluation/serializers/certificate/certificate.py b/core/apps/evaluation/serializers/certificate/certificate.py index 1a7bcdb..c094e3f 100644 --- a/core/apps/evaluation/serializers/certificate/certificate.py +++ b/core/apps/evaluation/serializers/certificate/certificate.py @@ -1,12 +1,25 @@ from rest_framework import serializers from core.apps.evaluation.models import CertificateModel + class BaseCertificateSerializer(serializers.ModelSerializer): + file_url = serializers.SerializerMethodField() class Meta: model = CertificateModel fields = [ "id", "title", - "file_url" - ] \ No newline at end of file + "file", + "file_url", + ] + + def get_file_url(self, obj): + request = self.context.get("request") + + if obj.file: + if request: + return request.build_absolute_uri(obj.file.url) + return obj.file.url + + return None \ No newline at end of file diff --git a/core/apps/evaluation/views/certificate.py b/core/apps/evaluation/views/certificate.py index a990840..ef5392e 100644 --- a/core/apps/evaluation/views/certificate.py +++ b/core/apps/evaluation/views/certificate.py @@ -5,6 +5,7 @@ from rest_framework.viewsets import ModelViewSet from core.apps.evaluation.models import CertificateModel from core.apps.evaluation.serializers.certificate import BaseCertificateSerializer from rest_framework.filters import SearchFilter +from rest_framework.parsers import MultiPartParser, FormParser @extend_schema(tags=["Certificate"]) class CertificateView(BaseViewSetMixin, ModelViewSet): @@ -12,6 +13,8 @@ class CertificateView(BaseViewSetMixin, ModelViewSet): serializer_class = BaseCertificateSerializer permission_classes = [IsAuthenticated] + parser_classes = [MultiPartParser, FormParser] + filter_backends = [SearchFilter] search_fields = ["title"] From 6eed2d998ec4aa8b33aec572175e50ffbb3f3b62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 23 Apr 2026 13:07:08 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=94=84=20Update=20image=20to=20112=20?= =?UTF-8?q?[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/urls.py | 2 +- stack.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/urls.py b/config/urls.py index 78d1fe5..c45dddd 100644 --- a/config/urls.py +++ b/config/urls.py @@ -13,7 +13,7 @@ from config.env import env def home(request): - return HttpResponse("OK: #6e0718c5dbc0c00aac698272f4a2cfde074453fa") + return HttpResponse("OK: #2c8269116651c45eba04f881a2959fddf9732a0c") urlpatterns = [ diff --git a/stack.yaml b/stack.yaml index 7db9338..27be01d 100644 --- a/stack.yaml +++ b/stack.yaml @@ -84,7 +84,7 @@ services: max-file: "5" web: - image: husanjon/sifatbaho:111 + image: husanjon/sifatbaho:112 env_file: - .env environment: @@ -129,7 +129,7 @@ services: max-file: "5" celery: - image: husanjon/sifatbaho:111 + image: husanjon/sifatbaho:112 env_file: - .env environment: From 6456283f721ceadea9372984c8ae325cbde65815 Mon Sep 17 00:00:00 2001 From: komoliddin Date: Thu, 23 Apr 2026 18:59:06 +0500 Subject: [PATCH 3/8] makemigrations --- ...move_certificatemodel_file_url_and_more.py | 22 +++++++++++++++++++ core/apps/evaluation/views/certificate.py | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 core/apps/evaluation/migrations/0034_remove_certificatemodel_file_url_and_more.py diff --git a/core/apps/evaluation/migrations/0034_remove_certificatemodel_file_url_and_more.py b/core/apps/evaluation/migrations/0034_remove_certificatemodel_file_url_and_more.py new file mode 100644 index 0000000..21973b2 --- /dev/null +++ b/core/apps/evaluation/migrations/0034_remove_certificatemodel_file_url_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 6.0.4 on 2026-04-23 13:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evaluation', '0033_merge_20260423_1622'), + ] + + operations = [ + migrations.RemoveField( + model_name='certificatemodel', + name='file_url', + ), + migrations.AddField( + model_name='certificatemodel', + name='file', + field=models.FileField(blank=True, null=True, upload_to='certificates/', verbose_name='file'), + ), + ] diff --git a/core/apps/evaluation/views/certificate.py b/core/apps/evaluation/views/certificate.py index ef5392e..5df696a 100644 --- a/core/apps/evaluation/views/certificate.py +++ b/core/apps/evaluation/views/certificate.py @@ -7,7 +7,7 @@ from core.apps.evaluation.serializers.certificate import BaseCertificateSerializ from rest_framework.filters import SearchFilter from rest_framework.parsers import MultiPartParser, FormParser -@extend_schema(tags=["Certificate"]) +@extend_schema(tags=["Certificate"],request=BaseCertificateSerializer) class CertificateView(BaseViewSetMixin, ModelViewSet): queryset = CertificateModel.objects.all() serializer_class = BaseCertificateSerializer From 07f8d55966583cdc2108c806a05b2b7cb6769930 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 23 Apr 2026 14:02:58 +0000 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=94=84=20Update=20image=20to=20113=20?= =?UTF-8?q?[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/urls.py | 2 +- stack.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/urls.py b/config/urls.py index c45dddd..078bd56 100644 --- a/config/urls.py +++ b/config/urls.py @@ -13,7 +13,7 @@ from config.env import env def home(request): - return HttpResponse("OK: #2c8269116651c45eba04f881a2959fddf9732a0c") + return HttpResponse("OK: #b0b4ccfeee7a581cff6bd5398595fff38f323607") urlpatterns = [ diff --git a/stack.yaml b/stack.yaml index 27be01d..840e660 100644 --- a/stack.yaml +++ b/stack.yaml @@ -84,7 +84,7 @@ services: max-file: "5" web: - image: husanjon/sifatbaho:112 + image: husanjon/sifatbaho:113 env_file: - .env environment: @@ -129,7 +129,7 @@ services: max-file: "5" celery: - image: husanjon/sifatbaho:112 + image: husanjon/sifatbaho:113 env_file: - .env environment: From 3b62c5a7bfefc132e1c80d9eda962a6fe28502ff Mon Sep 17 00:00:00 2001 From: komoliddin Date: Fri, 24 Apr 2026 10:14:01 +0500 Subject: [PATCH 5/8] Refactor URL patterns for evaluation archiving and remove unused file_url field from BaseCertificateSerializer --- .../serializers/certificate/certificate.py | 14 +------------- core/apps/evaluation/urls.py | 4 ++-- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/core/apps/evaluation/serializers/certificate/certificate.py b/core/apps/evaluation/serializers/certificate/certificate.py index c094e3f..b9afd95 100644 --- a/core/apps/evaluation/serializers/certificate/certificate.py +++ b/core/apps/evaluation/serializers/certificate/certificate.py @@ -3,7 +3,6 @@ from core.apps.evaluation.models import CertificateModel class BaseCertificateSerializer(serializers.ModelSerializer): - file_url = serializers.SerializerMethodField() class Meta: model = CertificateModel @@ -11,15 +10,4 @@ class BaseCertificateSerializer(serializers.ModelSerializer): "id", "title", "file", - "file_url", - ] - - def get_file_url(self, obj): - request = self.context.get("request") - - if obj.file: - if request: - return request.build_absolute_uri(obj.file.url) - return obj.file.url - - return None \ No newline at end of file + ] \ No newline at end of file diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index 8b25f9f..c27c9b0 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -78,6 +78,6 @@ urlpatterns = [ ), path("evaluation-request//change-status/", EvaluationStatusChange.as_view(), name="evaluation-change-status"), - path("quick-evaluation/archive/", ArchiveQuickEvaluationView.as_view(), name="quick-evaluation-archive"), - path("evaluation-request/archive/", ArchiveEvaluationrequestView.as_view(), name="evaluation-request-archive"), + path("archive/quick-evaluation/", ArchiveQuickEvaluationView.as_view(), name="quick-evaluation-archive"), + path("archive/evaluation-request/", ArchiveEvaluationrequestView.as_view(), name="evaluation-request-archive"), ] From 190480b6f730d11efac1c0a7f7ba2d92fab761fe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Apr 2026 05:16:20 +0000 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=94=84=20Update=20image=20to=20114=20?= =?UTF-8?q?[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/urls.py | 2 +- stack.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/urls.py b/config/urls.py index 078bd56..18874d4 100644 --- a/config/urls.py +++ b/config/urls.py @@ -13,7 +13,7 @@ from config.env import env def home(request): - return HttpResponse("OK: #b0b4ccfeee7a581cff6bd5398595fff38f323607") + return HttpResponse("OK: #1a985ffa4b785b63a71b9e0cdd78042c3fcda239") urlpatterns = [ diff --git a/stack.yaml b/stack.yaml index 840e660..41f18ce 100644 --- a/stack.yaml +++ b/stack.yaml @@ -84,7 +84,7 @@ services: max-file: "5" web: - image: husanjon/sifatbaho:113 + image: husanjon/sifatbaho:114 env_file: - .env environment: @@ -129,7 +129,7 @@ services: max-file: "5" celery: - image: husanjon/sifatbaho:113 + image: husanjon/sifatbaho:114 env_file: - .env environment: From fb275a091aed230313beab89c196c65ec656b797 Mon Sep 17 00:00:00 2001 From: komoliddin Date: Fri, 24 Apr 2026 11:21:01 +0500 Subject: [PATCH 7/8] Add view for crud user --- core/apps/accounts/serializers/user.py | 13 +++++++++++++ core/apps/accounts/urls.py | 3 ++- core/apps/accounts/views/user.py | 18 +++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/core/apps/accounts/serializers/user.py b/core/apps/accounts/serializers/user.py index 4f3276e..2a3d902 100644 --- a/core/apps/accounts/serializers/user.py +++ b/core/apps/accounts/serializers/user.py @@ -30,3 +30,16 @@ class UserUpdateSerializer(serializers.ModelSerializer): "last_name", "avatar" ] + +class AdminUserSerializer(serializers.ModelSerializer): + avatar = serializers.SerializerMethodField(method_name='get_avatar') + + class Meta: + model = get_user_model() + fields = "__all__" + + def get_avatar(self, obj): + request = self.context.get('request') + if obj.avatar: + return request.build_absolute_uri(obj.avatar.url) + return None \ No newline at end of file diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index f7a1e2d..45ae8fd 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -4,7 +4,7 @@ Accounts app urls from django.urls import path, include from rest_framework_simplejwt import views as jwt_views -from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, UserListApiView, AdminUserListApiView +from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, UserListApiView, AdminUserListApiView,AdminUserView from rest_framework.routers import DefaultRouter router = DefaultRouter() @@ -12,6 +12,7 @@ router.register("auth", RegisterView, basename="auth") router.register("auth", ResetPasswordView, basename="reset-password") router.register("auth", MeView, basename="me") router.register("auth", ChangePasswordView, basename="change-password") +router.register("user", AdminUserView, basename="user-crud") urlpatterns = [ diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index f9d4b9e..73a1b1b 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -5,8 +5,11 @@ from rest_framework.permissions import IsAuthenticated from drf_spectacular.utils import extend_schema -from core.apps.accounts.serializers.user import UserSerializer +from core.apps.accounts.serializers.user import UserSerializer, AdminUserSerializer from core.apps.accounts.choices.user import RoleChoice +from django_core.mixins import BaseViewSetMixin +from rest_framework.viewsets import ModelViewSet + User = get_user_model() @@ -29,3 +32,16 @@ class AdminUserListApiView(generics.ListAPIView): permission_classes = [IsAuthenticated] filter_backends = [filters.SearchFilter] search_fields = ['phone', 'first_name', 'last_name'] + + +@extend_schema(tags=["User"],request=AdminUserSerializer) +class AdminUserView(BaseViewSetMixin, ModelViewSet): + queryset = User.objects.filter(role=RoleChoice.USER) + serializer_class = AdminUserSerializer + permission_classes = [IsAuthenticated] + filter_backends = [filters.SearchFilter] + search_fields = ['phone', 'first_name', 'last_name'] + + def serializer_context(self): + return self.serializer_class(context={"request": self.request}) + From c89f2b32af0d7f5eec14facc99c5d3d0ef3f1455 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Apr 2026 06:23:17 +0000 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=94=84=20Update=20image=20to=20115=20?= =?UTF-8?q?[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/urls.py | 2 +- stack.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/urls.py b/config/urls.py index 18874d4..0e857fb 100644 --- a/config/urls.py +++ b/config/urls.py @@ -13,7 +13,7 @@ from config.env import env def home(request): - return HttpResponse("OK: #1a985ffa4b785b63a71b9e0cdd78042c3fcda239") + return HttpResponse("OK: #88dedd85c79ccf732b2adac03616bd14e67a1579") urlpatterns = [ diff --git a/stack.yaml b/stack.yaml index 41f18ce..1e72694 100644 --- a/stack.yaml +++ b/stack.yaml @@ -84,7 +84,7 @@ services: max-file: "5" web: - image: husanjon/sifatbaho:114 + image: husanjon/sifatbaho:115 env_file: - .env environment: @@ -129,7 +129,7 @@ services: max-file: "5" celery: - image: husanjon/sifatbaho:114 + image: husanjon/sifatbaho:115 env_file: - .env environment: