新增 admin 管理端完整 API,挂载在 /api/v1/admin/affinity/ 路径下:
- serializers.py:9 个序列化器
- AffinityRuleSerializer / AffinityLevelSerializer / AffinitySettingSerializer
含跨字段 validate(min/max 关系、区间重叠、衰减区间、companion_time 字段必填等)
- AffinityLogSerializer 只读 + 关联字段展开(user_username/device_code/rule_name)
- UserDeviceAffinitySerializer 含 device_code/mac/status/level_name
- AffinityAdjust + AffinityAdjustBatch 用 Serializer 而非 ModelSerializer
- permissions.py 中 IsAdminUserStaff 复用,所有 view 默认 RedisTokenAuthentication + IsAdminUserStaff
- views.py:7 个视图
- AffinityRuleAdminViewSet (P2-06):ModelViewSet + 软删 (is_deleted+is_enabled=False) + restore action;?include_deleted=true 返回全集
- AffinityLevelAdminViewSet (P2-07):同上软删;serializer 跨字段校验区间重叠
- AffinitySettingView (P2-08):APIView 单例 GET/PUT/PATCH;pk=1 硬约束
- AffinityLogListView (P2-09):过滤 user_id/device_id/rule_key/source/date_from/date_to;分页 page_size 上限 200;select_related 防 N+1
- AffinityStatsView (P2-10):avg/max/top_count/active_7d/total_devices/today_interactions/today_change_sum/rule_freq_top/level_distribution;全部基于 UserDevice.active 聚合;今日按 AffinitySetting.timezone 取 local date
- UserAffinityDevicesView (P2-11):?user_id= 必传 + 404 校验;?include_unbound=true 含历史;默认仅 is_bound=True
- AffinityAdjustView + AffinityAdjustBatchView (P2-12):委托 AffinityService.admin_adjust;批量遍历 UserDevice.active 逐台调用,返回 per-device 结果数组
- urls.py:DRF DefaultRouter 注册 rules/levels CRUD + 5 个独立 path 挂 settings/logs/stats/devices/adjust*
- admin_urls.py:引入 include 并新增 path('affinity/', include('userapp.affinity.urls'))
Django check 通过,6 URL reverse 全部解析正确:
/api/v1/admin/affinity/settings/
/api/v1/admin/affinity/logs/
/api/v1/admin/affinity/stats/
/api/v1/admin/affinity/devices/
/api/v1/admin/affinity/adjust/
/api/v1/admin/affinity/adjust-batch/
旧的 /api/user/affinity-rules/ 与 /affinity-levels/ 暂保留兼容,前端切到 admin 后即可清理。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
39 lines
1.4 KiB
Python
39 lines
1.4 KiB
Python
"""好感度系统 admin 端 URL 路由
|
||
|
||
挂载位置:`/api/v1/admin/affinity/...`(由 userapp/admin_urls.py include)
|
||
"""
|
||
|
||
from django.urls import path, include
|
||
from rest_framework.routers import DefaultRouter
|
||
|
||
from .views import (
|
||
AffinityAdjustBatchView,
|
||
AffinityAdjustView,
|
||
AffinityLevelAdminViewSet,
|
||
AffinityLogListView,
|
||
AffinityRuleAdminViewSet,
|
||
AffinitySettingView,
|
||
AffinityStatsView,
|
||
UserAffinityDevicesView,
|
||
)
|
||
|
||
router = DefaultRouter()
|
||
router.register('rules', AffinityRuleAdminViewSet, basename='admin-affinity-rule')
|
||
router.register('levels', AffinityLevelAdminViewSet, basename='admin-affinity-level')
|
||
|
||
urlpatterns = [
|
||
# P2-08 单例 settings
|
||
path('settings/', AffinitySettingView.as_view(), name='admin_affinity_settings'),
|
||
# P2-09 变更日志
|
||
path('logs/', AffinityLogListView.as_view(), name='admin_affinity_logs'),
|
||
# P2-10 统计
|
||
path('stats/', AffinityStatsView.as_view(), name='admin_affinity_stats'),
|
||
# P2-11 按用户列出设备
|
||
path('devices/', UserAffinityDevicesView.as_view(), name='admin_affinity_devices'),
|
||
# P2-12 手动调整
|
||
path('adjust/', AffinityAdjustView.as_view(), name='admin_affinity_adjust'),
|
||
path('adjust-batch/', AffinityAdjustBatchView.as_view(), name='admin_affinity_adjust_batch'),
|
||
# P2-06 / P2-07 router-driven CRUD
|
||
path('', include(router.urls)),
|
||
]
|