feat: implement LMS core (CMS, Courses, Enrollment, Progress, Auth) (Admin + API)
Build & Push Docker Image (Backend) / build (push) Successful in 54s
Build & Push Docker Image (Backend) / build (push) Successful in 54s
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
def auto_register(router, viewsets: dict):
|
||||
"""
|
||||
viewsets = {
|
||||
"articles": ArticleViewSet,
|
||||
"courses": CourseViewSet,
|
||||
}
|
||||
"""
|
||||
for prefix, viewset in viewsets.items():
|
||||
router.register(prefix, viewset, basename=prefix)
|
||||
@@ -0,0 +1,11 @@
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
|
||||
class BaseModelSerializer(ModelSerializer):
|
||||
"""
|
||||
Base Serializer สำหรับ CMS‑like API
|
||||
- ใช้ fields = "__all__" เป็น default
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
fields = "__all__"
|
||||
@@ -0,0 +1,29 @@
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.filters import SearchFilter, OrderingFilter
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
|
||||
class BaseModelViewSet(ModelViewSet):
|
||||
"""
|
||||
CMS-like Base ViewSet
|
||||
- CRUD อัตโนมัติ
|
||||
- Pagination (จาก settings.py)
|
||||
- Filter / Search / Ordering
|
||||
- Permission กลาง
|
||||
"""
|
||||
|
||||
# default permission (override ได้)
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
# filter backend มาตรฐานแบบ CMS
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
SearchFilter,
|
||||
OrderingFilter,
|
||||
]
|
||||
|
||||
# ค่า default (override ต่อ model)
|
||||
filterset_fields = "__all__"
|
||||
search_fields = []
|
||||
ordering_fields = "__all__"
|
||||
ordering = ["-id"]
|
||||
@@ -0,0 +1,12 @@
|
||||
from rest_framework.permissions import BasePermission, SAFE_METHODS
|
||||
|
||||
class IsStaffOrReadOnly(BasePermission):
|
||||
"""
|
||||
- อ่านได้ทุกคน
|
||||
- เขียนได้เฉพาะ staff
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if request.method in SAFE_METHODS:
|
||||
return True
|
||||
return request.user and request.user.is_staff
|
||||
+37
-6
@@ -1,7 +1,38 @@
|
||||
from django.urls import path
|
||||
|
||||
from apps.common.views import HealthCheckView
|
||||
|
||||
urlpatterns = [
|
||||
path("health/", HealthCheckView.as_view(), name="health-check"),
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from apps.common.api.auto_router import auto_register
|
||||
from apps.common.views import HealthCheckView
|
||||
from apps.content.views import ArticleViewSet
|
||||
from apps.courses.views import CourseViewSet
|
||||
|
||||
# Action-based Views (Enrollment / Progress)
|
||||
from apps.courses.views import (
|
||||
EnrollCourseView,
|
||||
MyCoursesView,
|
||||
CompleteLessonView,
|
||||
)
|
||||
|
||||
# Router สำหรับ CMS-like API
|
||||
router = DefaultRouter()
|
||||
|
||||
# ใช้ auto_register เฉพาะกับ CMS‑like resources
|
||||
auto_register(router, {
|
||||
"articles" : ArticleViewSet,
|
||||
"courses" : CourseViewSet,
|
||||
})
|
||||
|
||||
urlpatterns = [
|
||||
# Health check
|
||||
path("health/", HealthCheckView.as_view(), name="health-check"),
|
||||
|
||||
# CMS-like API
|
||||
path("api/", include(router.urls)),
|
||||
|
||||
# Enrollment (user ↔ course)
|
||||
path("api/courses/<int:course_id>/enroll/", EnrollCourseView.as_view(), name="enroll-course"),
|
||||
path("api/my/courses/", MyCoursesView.as_view(), name="my-courses"),
|
||||
|
||||
# Progress tracking (user ↔ lesson)
|
||||
path("api/lessons/<int:lesson_id>/complete/", CompleteLessonView.as_view(), name="complete-lesson"),
|
||||
]
|
||||
Reference in New Issue
Block a user