Enhance API documentation and schema management by implementing explicit tag configurations for Swagger and ReDoc. Introduce postprocessing hooks to filter auto-generated tags, ensuring only defined tags are used. Update viewsets across various modules to utilize the new tagging system, improving clarity and organization in API documentation.
This commit is contained in:
36
=0.27.0
Normal file
36
=0.27.0
Normal file
@@ -0,0 +1,36 @@
|
||||
Collecting drf-spectacular
|
||||
Downloading drf_spectacular-0.29.0-py3-none-any.whl.metadata (14 kB)
|
||||
Requirement already satisfied: Django>=2.2 in /usr/local/lib/python3.11/site-packages (from drf-spectacular) (5.2.8)
|
||||
Requirement already satisfied: djangorestframework>=3.10.3 in /usr/local/lib/python3.11/site-packages (from drf-spectacular) (3.16.1)
|
||||
Collecting uritemplate>=2.0.0 (from drf-spectacular)
|
||||
Downloading uritemplate-4.2.0-py3-none-any.whl.metadata (2.6 kB)
|
||||
Collecting PyYAML>=5.1 (from drf-spectacular)
|
||||
Downloading pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (2.4 kB)
|
||||
Collecting jsonschema>=2.6.0 (from drf-spectacular)
|
||||
Downloading jsonschema-4.25.1-py3-none-any.whl.metadata (7.6 kB)
|
||||
Collecting inflection>=0.3.1 (from drf-spectacular)
|
||||
Downloading inflection-0.5.1-py2.py3-none-any.whl.metadata (1.7 kB)
|
||||
Requirement already satisfied: asgiref>=3.8.1 in /usr/local/lib/python3.11/site-packages (from Django>=2.2->drf-spectacular) (3.10.0)
|
||||
Requirement already satisfied: sqlparse>=0.3.1 in /usr/local/lib/python3.11/site-packages (from Django>=2.2->drf-spectacular) (0.5.3)
|
||||
Collecting attrs>=22.2.0 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading attrs-25.4.0-py3-none-any.whl.metadata (10 kB)
|
||||
Collecting jsonschema-specifications>=2023.03.6 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl.metadata (2.9 kB)
|
||||
Collecting referencing>=0.28.4 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading referencing-0.37.0-py3-none-any.whl.metadata (2.8 kB)
|
||||
Collecting rpds-py>=0.7.1 (from jsonschema>=2.6.0->drf-spectacular)
|
||||
Downloading rpds_py-0.28.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.1 kB)
|
||||
Requirement already satisfied: typing-extensions>=4.4.0 in /usr/local/lib/python3.11/site-packages (from referencing>=0.28.4->jsonschema>=2.6.0->drf-spectacular) (4.15.0)
|
||||
Downloading drf_spectacular-0.29.0-py3-none-any.whl (105 kB)
|
||||
Downloading inflection-0.5.1-py2.py3-none-any.whl (9.5 kB)
|
||||
Downloading jsonschema-4.25.1-py3-none-any.whl (90 kB)
|
||||
Downloading attrs-25.4.0-py3-none-any.whl (67 kB)
|
||||
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl (18 kB)
|
||||
Downloading pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (806 kB)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 806.6/806.6 kB 7.8 MB/s 0:00:00
|
||||
Downloading referencing-0.37.0-py3-none-any.whl (26 kB)
|
||||
Downloading rpds_py-0.28.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (382 kB)
|
||||
Downloading uritemplate-4.2.0-py3-none-any.whl (11 kB)
|
||||
Installing collected packages: uritemplate, rpds-py, PyYAML, inflection, attrs, referencing, jsonschema-specifications, jsonschema, drf-spectacular
|
||||
|
||||
Successfully installed PyYAML-6.0.3 attrs-25.4.0 drf-spectacular-0.29.0 inflection-0.5.1 jsonschema-4.25.1 jsonschema-specifications-2025.9.1 referencing-0.37.0 rpds-py-0.28.0 uritemplate-4.2.0
|
||||
@@ -7,6 +7,52 @@ from drf_spectacular.plumbing import build_bearer_security_scheme_object
|
||||
from drf_spectacular.utils import extend_schema, OpenApiResponse
|
||||
from rest_framework import status
|
||||
|
||||
# Explicit tags we want to keep (from SPECTACULAR_SETTINGS)
|
||||
EXPLICIT_TAGS = {'Authentication', 'Planner', 'Writer', 'System', 'Billing'}
|
||||
|
||||
|
||||
def postprocess_schema_filter_tags(result, generator, request, public):
|
||||
"""
|
||||
Postprocessing hook to remove auto-generated tags and keep only explicit tags.
|
||||
This prevents duplicate tags from URL patterns (auth, planner, etc.)
|
||||
"""
|
||||
# First, filter tags from all paths (operations)
|
||||
if 'paths' in result:
|
||||
for path, methods in result['paths'].items():
|
||||
for method, operation in methods.items():
|
||||
if isinstance(operation, dict) and 'tags' in operation:
|
||||
# Keep only explicit tags from the operation
|
||||
filtered_tags = [
|
||||
tag for tag in operation['tags']
|
||||
if tag in EXPLICIT_TAGS
|
||||
]
|
||||
|
||||
# If no explicit tags found, infer from path
|
||||
if not filtered_tags:
|
||||
if '/auth/' in path or '/api/v1/auth/' in path:
|
||||
filtered_tags = ['Authentication']
|
||||
elif '/planner/' in path or '/api/v1/planner/' in path:
|
||||
filtered_tags = ['Planner']
|
||||
elif '/writer/' in path or '/api/v1/writer/' in path:
|
||||
filtered_tags = ['Writer']
|
||||
elif '/system/' in path or '/api/v1/system/' in path:
|
||||
filtered_tags = ['System']
|
||||
elif '/billing/' in path or '/api/v1/billing/' in path:
|
||||
filtered_tags = ['Billing']
|
||||
|
||||
operation['tags'] = filtered_tags
|
||||
|
||||
# Now filter the tags list - keep only explicit tag definitions
|
||||
# The tags list contains tag definitions with 'name' and 'description'
|
||||
if 'tags' in result and isinstance(result['tags'], list):
|
||||
# Keep only tags that match our explicit tag names
|
||||
result['tags'] = [
|
||||
tag for tag in result['tags']
|
||||
if isinstance(tag, dict) and tag.get('name') in EXPLICIT_TAGS
|
||||
]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class JWTAuthenticationExtension(OpenApiAuthenticationExtension):
|
||||
"""
|
||||
|
||||
@@ -7,10 +7,11 @@ from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status, permissions
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from .views import (
|
||||
GroupsViewSet, UsersViewSet, AccountsViewSet, SubscriptionsViewSet,
|
||||
SiteUserAccessViewSet, PlanViewSet, SiteViewSet, SectorViewSet,
|
||||
IndustryViewSet, SeedKeywordViewSet, AuthViewSet
|
||||
IndustryViewSet, SeedKeywordViewSet
|
||||
)
|
||||
from .serializers import RegisterSerializer, LoginSerializer, ChangePasswordSerializer, UserSerializer
|
||||
from .models import User
|
||||
@@ -29,9 +30,14 @@ router.register(r'sites', SiteViewSet, basename='site')
|
||||
router.register(r'sectors', SectorViewSet, basename='sector')
|
||||
router.register(r'industries', IndustryViewSet, basename='industry')
|
||||
router.register(r'seed-keywords', SeedKeywordViewSet, basename='seed-keyword')
|
||||
router.register(r'auth', AuthViewSet, basename='auth')
|
||||
# Note: AuthViewSet removed - using direct APIView endpoints instead (login, register, etc.)
|
||||
|
||||
|
||||
@extend_schema(
|
||||
tags=['Authentication'],
|
||||
summary='User Registration',
|
||||
description='Register a new user account'
|
||||
)
|
||||
class RegisterView(APIView):
|
||||
"""Registration endpoint."""
|
||||
permission_classes = [permissions.AllowAny]
|
||||
@@ -52,6 +58,11 @@ class RegisterView(APIView):
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@extend_schema(
|
||||
tags=['Authentication'],
|
||||
summary='User Login',
|
||||
description='Authenticate user and receive JWT tokens'
|
||||
)
|
||||
class LoginView(APIView):
|
||||
"""Login endpoint."""
|
||||
permission_classes = [permissions.AllowAny]
|
||||
@@ -123,6 +134,11 @@ class LoginView(APIView):
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@extend_schema(
|
||||
tags=['Authentication'],
|
||||
summary='Change Password',
|
||||
description='Change user password'
|
||||
)
|
||||
class ChangePasswordView(APIView):
|
||||
"""Change password endpoint."""
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
@@ -151,6 +167,11 @@ class ChangePasswordView(APIView):
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@extend_schema(
|
||||
tags=['Authentication'],
|
||||
summary='Get Current User',
|
||||
description='Get information about the currently authenticated user'
|
||||
)
|
||||
class MeView(APIView):
|
||||
"""Get current user information."""
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
@@ -10,6 +10,7 @@ from django.contrib.auth import authenticate
|
||||
from django.utils import timezone
|
||||
from django.db import transaction
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAuthentication
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
@@ -33,6 +34,10 @@ import jwt
|
||||
# 1. GROUPS - Define user roles and permissions across the system
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class GroupsViewSet(viewsets.ViewSet):
|
||||
"""
|
||||
ViewSet for managing user roles and permissions (Groups).
|
||||
@@ -119,6 +124,14 @@ class GroupsViewSet(viewsets.ViewSet):
|
||||
# 2. USERS - Manage global user records and credentials
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
create=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
update=extend_schema(tags=['Authentication']),
|
||||
partial_update=extend_schema(tags=['Authentication']),
|
||||
destroy=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class UsersViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing global user records and credentials.
|
||||
@@ -246,6 +259,14 @@ class UsersViewSet(AccountModelViewSet):
|
||||
# 3. ACCOUNTS - Register each unique organization/user space
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
create=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
update=extend_schema(tags=['Authentication']),
|
||||
partial_update=extend_schema(tags=['Authentication']),
|
||||
destroy=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class AccountsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing accounts (unique organization/user spaces).
|
||||
@@ -303,6 +324,14 @@ class AccountsViewSet(AccountModelViewSet):
|
||||
# 4. SUBSCRIPTIONS - Control plan level, limits, and billing per account
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
create=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
update=extend_schema(tags=['Authentication']),
|
||||
partial_update=extend_schema(tags=['Authentication']),
|
||||
destroy=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class SubscriptionsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing subscriptions (plan level, limits, billing per account).
|
||||
@@ -356,6 +385,14 @@ class SubscriptionsViewSet(AccountModelViewSet):
|
||||
# 5. SITE USER ACCESS - Assign users access to specific sites within account
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
create=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
update=extend_schema(tags=['Authentication']),
|
||||
partial_update=extend_schema(tags=['Authentication']),
|
||||
destroy=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class SiteUserAccessViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing Site-User access permissions.
|
||||
@@ -394,6 +431,10 @@ class SiteUserAccessViewSet(AccountModelViewSet):
|
||||
# SUPPORTING VIEWSETS (Sites, Sectors, Industries, Plans, Auth)
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class PlanViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""
|
||||
ViewSet for listing active subscription plans.
|
||||
@@ -420,6 +461,14 @@ class PlanViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
create=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
update=extend_schema(tags=['Authentication']),
|
||||
partial_update=extend_schema(tags=['Authentication']),
|
||||
destroy=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class SiteViewSet(AccountModelViewSet):
|
||||
"""ViewSet for managing Sites."""
|
||||
serializer_class = SiteSerializer
|
||||
@@ -655,6 +704,14 @@ class SiteViewSet(AccountModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
create=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
update=extend_schema(tags=['Authentication']),
|
||||
partial_update=extend_schema(tags=['Authentication']),
|
||||
destroy=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class SectorViewSet(AccountModelViewSet):
|
||||
"""ViewSet for managing Sectors."""
|
||||
serializer_class = SectorSerializer
|
||||
@@ -692,6 +749,10 @@ class SectorViewSet(AccountModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class IndustryViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""
|
||||
ViewSet for industry templates.
|
||||
@@ -727,6 +788,10 @@ class IndustryViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Authentication']),
|
||||
retrieve=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class SeedKeywordViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""
|
||||
ViewSet for SeedKeyword - Global reference data (read-only for non-admins).
|
||||
@@ -776,6 +841,12 @@ class SeedKeywordViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
# AUTHENTICATION ENDPOINTS (Register, Login, Change Password, Me)
|
||||
# ============================================================================
|
||||
|
||||
@extend_schema_view(
|
||||
register=extend_schema(tags=['Authentication']),
|
||||
login=extend_schema(tags=['Authentication']),
|
||||
change_password=extend_schema(tags=['Authentication']),
|
||||
refresh_token=extend_schema(tags=['Authentication']),
|
||||
)
|
||||
class AuthViewSet(viewsets.GenericViewSet):
|
||||
"""Authentication endpoints.
|
||||
Unified API Standard v1.0 compliant
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.db.models import Sum, Count, Q
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
@@ -23,6 +24,9 @@ from .services import CreditService
|
||||
from .exceptions import InsufficientCreditsError
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Billing']),
|
||||
)
|
||||
class CreditBalanceViewSet(viewsets.ViewSet):
|
||||
"""
|
||||
ViewSet for credit balance operations
|
||||
@@ -73,6 +77,10 @@ class CreditBalanceViewSet(viewsets.ViewSet):
|
||||
return success_response(data=serializer.data, request=request)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Billing']),
|
||||
retrieve=extend_schema(tags=['Billing']),
|
||||
)
|
||||
class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""
|
||||
ViewSet for credit usage logs
|
||||
@@ -444,6 +452,10 @@ class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
return success_response(data={'limits': limits_data}, request=request)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Billing']),
|
||||
retrieve=extend_schema(tags=['Billing']),
|
||||
)
|
||||
class CreditTransactionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""
|
||||
ViewSet for credit transaction history
|
||||
|
||||
@@ -8,6 +8,7 @@ from django.http import HttpResponse
|
||||
import csv
|
||||
import json
|
||||
import time
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import SiteSectorModelViewSet
|
||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
@@ -18,6 +19,14 @@ from .serializers import KeywordSerializer, ContentIdeasSerializer
|
||||
from .cluster_serializers import ClusterSerializer
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Planner']),
|
||||
create=extend_schema(tags=['Planner']),
|
||||
retrieve=extend_schema(tags=['Planner']),
|
||||
update=extend_schema(tags=['Planner']),
|
||||
partial_update=extend_schema(tags=['Planner']),
|
||||
destroy=extend_schema(tags=['Planner']),
|
||||
)
|
||||
class KeywordViewSet(SiteSectorModelViewSet):
|
||||
"""
|
||||
ViewSet for managing keywords with CRUD operations
|
||||
@@ -662,6 +671,14 @@ class KeywordViewSet(SiteSectorModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Planner']),
|
||||
create=extend_schema(tags=['Planner']),
|
||||
retrieve=extend_schema(tags=['Planner']),
|
||||
update=extend_schema(tags=['Planner']),
|
||||
partial_update=extend_schema(tags=['Planner']),
|
||||
destroy=extend_schema(tags=['Planner']),
|
||||
)
|
||||
class ClusterViewSet(SiteSectorModelViewSet):
|
||||
"""
|
||||
ViewSet for managing clusters with CRUD operations
|
||||
@@ -952,6 +969,14 @@ class ClusterViewSet(SiteSectorModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Planner']),
|
||||
create=extend_schema(tags=['Planner']),
|
||||
retrieve=extend_schema(tags=['Planner']),
|
||||
update=extend_schema(tags=['Planner']),
|
||||
partial_update=extend_schema(tags=['Planner']),
|
||||
destroy=extend_schema(tags=['Planner']),
|
||||
)
|
||||
class ContentIdeasViewSet(SiteSectorModelViewSet):
|
||||
"""
|
||||
ViewSet for managing content ideas with CRUD operations
|
||||
|
||||
@@ -7,6 +7,7 @@ from rest_framework import viewsets, status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from django.db import transaction
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||
@@ -16,6 +17,14 @@ from django.conf import settings
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
test_connection=extend_schema(tags=['System']),
|
||||
task_progress=extend_schema(tags=['System']),
|
||||
get_image_generation_settings=extend_schema(tags=['System']),
|
||||
)
|
||||
class IntegrationSettingsViewSet(viewsets.ViewSet):
|
||||
"""
|
||||
ViewSet for managing integration settings (OpenAI, Runware, GSC)
|
||||
|
||||
@@ -6,6 +6,7 @@ from rest_framework import viewsets, status, permissions
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from django.db import transaction
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAuthentication
|
||||
@@ -18,6 +19,14 @@ from .settings_serializers import (
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class SystemSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing system-wide settings (admin only for write operations)
|
||||
@@ -61,6 +70,14 @@ class SystemSettingsViewSet(AccountModelViewSet):
|
||||
return success_response(data=serializer.data, request=request)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class AccountSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing account-level settings
|
||||
@@ -113,6 +130,14 @@ class AccountSettingsViewSet(AccountModelViewSet):
|
||||
serializer.save(account=account)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class UserSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing user-level settings
|
||||
@@ -171,6 +196,14 @@ class UserSettingsViewSet(AccountModelViewSet):
|
||||
serializer.save(user=user, account=account)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class ModuleSettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing module-specific settings
|
||||
@@ -242,6 +275,14 @@ class ModuleSettingsViewSet(AccountModelViewSet):
|
||||
serializer.save(account=account)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class AISettingsViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing AI-specific settings
|
||||
|
||||
@@ -12,6 +12,7 @@ from django.db import transaction, connection
|
||||
from django.core.cache import cache
|
||||
from django.utils import timezone
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import AccountModelViewSet
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.permissions import IsEditorOrAbove, IsAuthenticatedAndActive, IsViewerOrAbove
|
||||
@@ -23,6 +24,14 @@ from .serializers import AIPromptSerializer, AuthorProfileSerializer, StrategySe
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class AIPromptViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing AI prompts
|
||||
@@ -192,6 +201,14 @@ class AIPromptViewSet(AccountModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class AuthorProfileViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing Author Profiles
|
||||
@@ -210,6 +227,14 @@ class AuthorProfileViewSet(AccountModelViewSet):
|
||||
filterset_fields = ['is_active', 'language']
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['System']),
|
||||
create=extend_schema(tags=['System']),
|
||||
retrieve=extend_schema(tags=['System']),
|
||||
update=extend_schema(tags=['System']),
|
||||
partial_update=extend_schema(tags=['System']),
|
||||
destroy=extend_schema(tags=['System']),
|
||||
)
|
||||
class StrategyViewSet(AccountModelViewSet):
|
||||
"""
|
||||
ViewSet for managing Strategies
|
||||
|
||||
@@ -4,6 +4,7 @@ from rest_framework.response import Response
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from django.db import transaction, models
|
||||
from django.db.models import Q
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
from igny8_core.api.base import SiteSectorModelViewSet
|
||||
from igny8_core.api.pagination import CustomPageNumberPagination
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
@@ -13,6 +14,14 @@ from .models import Tasks, Images, Content
|
||||
from .serializers import TasksSerializer, ImagesSerializer, ContentSerializer
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Writer']),
|
||||
create=extend_schema(tags=['Writer']),
|
||||
retrieve=extend_schema(tags=['Writer']),
|
||||
update=extend_schema(tags=['Writer']),
|
||||
partial_update=extend_schema(tags=['Writer']),
|
||||
destroy=extend_schema(tags=['Writer']),
|
||||
)
|
||||
class TasksViewSet(SiteSectorModelViewSet):
|
||||
"""
|
||||
ViewSet for managing tasks with CRUD operations
|
||||
@@ -374,6 +383,14 @@ class TasksViewSet(SiteSectorModelViewSet):
|
||||
)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Writer']),
|
||||
create=extend_schema(tags=['Writer']),
|
||||
retrieve=extend_schema(tags=['Writer']),
|
||||
update=extend_schema(tags=['Writer']),
|
||||
partial_update=extend_schema(tags=['Writer']),
|
||||
destroy=extend_schema(tags=['Writer']),
|
||||
)
|
||||
class ImagesViewSet(SiteSectorModelViewSet):
|
||||
"""
|
||||
ViewSet for managing content images
|
||||
@@ -773,6 +790,14 @@ class ImagesViewSet(SiteSectorModelViewSet):
|
||||
request=request
|
||||
)
|
||||
|
||||
@extend_schema_view(
|
||||
list=extend_schema(tags=['Writer']),
|
||||
create=extend_schema(tags=['Writer']),
|
||||
retrieve=extend_schema(tags=['Writer']),
|
||||
update=extend_schema(tags=['Writer']),
|
||||
partial_update=extend_schema(tags=['Writer']),
|
||||
destroy=extend_schema(tags=['Writer']),
|
||||
)
|
||||
class ContentViewSet(SiteSectorModelViewSet):
|
||||
"""
|
||||
ViewSet for managing task content
|
||||
|
||||
@@ -331,7 +331,8 @@ SPECTACULAR_SETTINGS = {
|
||||
# Include request/response examples
|
||||
'SERVE_PERMISSIONS': ['rest_framework.permissions.AllowAny'],
|
||||
'SERVE_AUTHENTICATION': None, # Allow unauthenticated access to docs
|
||||
# Tags for grouping endpoints
|
||||
|
||||
# Tag configuration - prevent auto-generation and use explicit tags
|
||||
'TAGS': [
|
||||
{'name': 'Authentication', 'description': 'User authentication and registration'},
|
||||
{'name': 'Planner', 'description': 'Keywords, clusters, and content ideas'},
|
||||
@@ -339,6 +340,54 @@ SPECTACULAR_SETTINGS = {
|
||||
{'name': 'System', 'description': 'Settings, prompts, and integrations'},
|
||||
{'name': 'Billing', 'description': 'Credits, usage, and transactions'},
|
||||
],
|
||||
'TAGS_ORDER': ['Authentication', 'Planner', 'Writer', 'System', 'Billing'],
|
||||
# Postprocessing hook to filter out auto-generated tags
|
||||
'POSTPROCESSING_HOOKS': ['igny8_core.api.schema_extensions.postprocess_schema_filter_tags'],
|
||||
|
||||
# Swagger UI configuration
|
||||
'SWAGGER_UI_SETTINGS': {
|
||||
'deepLinking': True,
|
||||
'displayOperationId': False,
|
||||
'defaultModelsExpandDepth': 1, # Collapse models by default
|
||||
'defaultModelExpandDepth': 1, # Collapse model properties by default
|
||||
'defaultModelRendering': 'model', # Show models in a cleaner format
|
||||
'displayRequestDuration': True,
|
||||
'docExpansion': 'none', # Collapse all operations by default
|
||||
'filter': True, # Enable filter box
|
||||
'showExtensions': True,
|
||||
'showCommonExtensions': True,
|
||||
'tryItOutEnabled': True, # Enable "Try it out" by default
|
||||
},
|
||||
|
||||
# ReDoc configuration
|
||||
'REDOC_UI_SETTINGS': {
|
||||
'hideDownloadButton': False,
|
||||
'hideHostname': False,
|
||||
'hideLoading': False,
|
||||
'hideSingleRequestSampleTab': False,
|
||||
'expandResponses': '200,201', # Expand successful responses
|
||||
'jsonSampleExpandLevel': 2, # Expand JSON samples 2 levels
|
||||
'hideFab': False,
|
||||
'theme': {
|
||||
'colors': {
|
||||
'primary': {
|
||||
'main': '#32329f'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
# Schema presentation improvements
|
||||
'SCHEMA_COERCE_PATH_PK': True,
|
||||
'SCHEMA_COERCE_METHOD_NAMES': {
|
||||
'retrieve': 'get',
|
||||
'list': 'list',
|
||||
'create': 'post',
|
||||
'update': 'put',
|
||||
'partial_update': 'patch',
|
||||
'destroy': 'delete',
|
||||
},
|
||||
|
||||
# Custom response format documentation
|
||||
'EXTENSIONS_INFO': {
|
||||
'x-code-samples': [
|
||||
|
||||
Reference in New Issue
Block a user