增加了api功能:
创建API文档页面 :新建了 status/templates/status/api_docs.html 模板文件,包含:
- API认证方式说明
- 所有API端点的详细说明(POST /api/checkin/、GET /api/services/、GET /api/services/{id}/history/、GET /api/status-summary/)
- 每个端点的请求体和响应体示例
- 状态码和检测类型的说明
This commit is contained in:
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
12
status/api_urls.py
Normal file
12
status/api_urls.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from django.urls import path
|
||||||
|
from . import api_views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# 客户端上报接口
|
||||||
|
path('checkin/', api_views.CheckInAPIView.as_view(), name='api-checkin'),
|
||||||
|
|
||||||
|
# 查询接口
|
||||||
|
path('services/', api_views.ServiceListAPIView.as_view(), name='api-service-list'),
|
||||||
|
path('services/<int:service_id>/history/', api_views.ServiceHistoryAPIView.as_view(), name='api-service-history'),
|
||||||
|
path('status-summary/', api_views.StatusSummaryAPIView.as_view(), name='api-status-summary'),
|
||||||
|
]
|
||||||
142
status/api_views.py
Normal file
142
status/api_views.py
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
from rest_framework import status, generics
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from django.db.models import Count, Q
|
||||||
|
from .models import Service, ServiceCheckRecord, ServiceGroup
|
||||||
|
from .serializers import (
|
||||||
|
ServiceSerializer,
|
||||||
|
ServiceCheckRecordSerializer,
|
||||||
|
ServiceCheckInSerializer,
|
||||||
|
StatusSummarySerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
# 引入loguru库用于日志记录
|
||||||
|
try:
|
||||||
|
from loguru import logger
|
||||||
|
except ImportError:
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckInAPIView(APIView):
|
||||||
|
"""客户端上报接口"""
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""处理客户端上报请求"""
|
||||||
|
serializer = ServiceCheckInSerializer(data=request.data)
|
||||||
|
|
||||||
|
if serializer.is_valid():
|
||||||
|
try:
|
||||||
|
result = serializer.create(serializer.validated_data)
|
||||||
|
logger.info(f"服务上报成功,服务ID: {result['service_id']}")
|
||||||
|
return Response({
|
||||||
|
"code": status.HTTP_200_OK,
|
||||||
|
"message": "上报成功",
|
||||||
|
"service_id": result['service_id']
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"服务上报失败: {str(e)}")
|
||||||
|
return Response({
|
||||||
|
"code": status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
"message": f"上报失败: {str(e)}"
|
||||||
|
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||||
|
else:
|
||||||
|
logger.warning(f"服务上报数据无效: {serializer.errors}")
|
||||||
|
return Response({
|
||||||
|
"code": status.HTTP_400_BAD_REQUEST,
|
||||||
|
"message": "数据无效",
|
||||||
|
"errors": serializer.errors
|
||||||
|
}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceListAPIView(generics.ListAPIView):
|
||||||
|
"""获取所有服务列表(含最新状态)"""
|
||||||
|
serializer_class = ServiceSerializer
|
||||||
|
queryset = Service.objects.all().select_related('group')
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super().get_queryset()
|
||||||
|
|
||||||
|
# 支持按分组过滤
|
||||||
|
group_name = self.request.query_params.get('group')
|
||||||
|
if group_name:
|
||||||
|
queryset = queryset.filter(group__name=group_name)
|
||||||
|
|
||||||
|
# 支持按状态过滤
|
||||||
|
status_filter = self.request.query_params.get('status')
|
||||||
|
if status_filter:
|
||||||
|
# 获取每个服务的最新状态
|
||||||
|
service_ids_with_status = []
|
||||||
|
for service in queryset:
|
||||||
|
if service.get_latest_status() == status_filter.upper():
|
||||||
|
service_ids_with_status.append(service.id)
|
||||||
|
queryset = queryset.filter(id__in=service_ids_with_status)
|
||||||
|
|
||||||
|
# 支持按名称搜索
|
||||||
|
search = self.request.query_params.get('search')
|
||||||
|
if search:
|
||||||
|
queryset = queryset.filter(
|
||||||
|
Q(name__icontains=search) |
|
||||||
|
Q(host__icontains=search) |
|
||||||
|
Q(description__icontains=search)
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"获取服务列表,过滤参数: group={group_name}, status={status_filter}, search={search}")
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceHistoryAPIView(generics.ListAPIView):
|
||||||
|
"""获取某服务历史记录(分页)"""
|
||||||
|
serializer_class = ServiceCheckRecordSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
service_id = self.kwargs.get('service_id')
|
||||||
|
try:
|
||||||
|
service = Service.objects.get(id=service_id)
|
||||||
|
except Service.DoesNotExist:
|
||||||
|
logger.warning(f"请求的服务不存在,ID: {service_id}")
|
||||||
|
return ServiceCheckRecord.objects.none()
|
||||||
|
|
||||||
|
queryset = ServiceCheckRecord.objects.filter(service=service)
|
||||||
|
logger.info(f"获取服务历史记录,服务ID: {service_id}")
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class StatusSummaryAPIView(APIView):
|
||||||
|
"""获取全局状态摘要"""
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
"""获取全局状态摘要"""
|
||||||
|
services = Service.objects.all()
|
||||||
|
total_services = services.count()
|
||||||
|
|
||||||
|
up_services = 0
|
||||||
|
down_services = 0
|
||||||
|
unknown_services = 0
|
||||||
|
|
||||||
|
for service in services:
|
||||||
|
latest_status = service.get_latest_status()
|
||||||
|
if latest_status == 'UP':
|
||||||
|
up_services += 1
|
||||||
|
elif latest_status == 'DOWN':
|
||||||
|
down_services += 1
|
||||||
|
else:
|
||||||
|
unknown_services += 1
|
||||||
|
|
||||||
|
# 计算正常运行时间百分比
|
||||||
|
if total_services > 0:
|
||||||
|
uptime_percentage = (up_services / total_services) * 100
|
||||||
|
else:
|
||||||
|
uptime_percentage = 0
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'total_services': total_services,
|
||||||
|
'up_services': up_services,
|
||||||
|
'down_services': down_services,
|
||||||
|
'unknown_services': unknown_services,
|
||||||
|
'uptime_percentage': round(uptime_percentage, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer = StatusSummarySerializer(data)
|
||||||
|
logger.info(f"获取状态摘要: {data}")
|
||||||
|
return Response(serializer.data)
|
||||||
@@ -43,6 +43,27 @@ class Service(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name} ({self.host})"
|
return f"{self.name} ({self.host})"
|
||||||
|
|
||||||
|
def get_latest_status(self):
|
||||||
|
"""获取最新状态"""
|
||||||
|
latest_record = self.records.first()
|
||||||
|
if latest_record:
|
||||||
|
return latest_record.status
|
||||||
|
return 'UNKNOWN'
|
||||||
|
|
||||||
|
def get_latest_check_time(self):
|
||||||
|
"""获取最新检测时间"""
|
||||||
|
latest_record = self.records.first()
|
||||||
|
if latest_record:
|
||||||
|
return latest_record.checked_at
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_latest_response_time(self):
|
||||||
|
"""获取最新响应时间"""
|
||||||
|
latest_record = self.records.first()
|
||||||
|
if latest_record:
|
||||||
|
return latest_record.response_time
|
||||||
|
return None
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '服务'
|
verbose_name = '服务'
|
||||||
verbose_name_plural = '服务'
|
verbose_name_plural = '服务'
|
||||||
|
|||||||
96
status/serializers.py
Normal file
96
status/serializers.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from .models import ServiceGroup, Service, ServiceCheckRecord
|
||||||
|
|
||||||
|
# 引入loguru库用于日志记录
|
||||||
|
try:
|
||||||
|
from loguru import logger
|
||||||
|
except ImportError:
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceGroupSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ServiceGroup
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceCheckRecordSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ServiceCheckRecord
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceSerializer(serializers.ModelSerializer):
|
||||||
|
latest_status = serializers.CharField(source='get_latest_status', read_only=True)
|
||||||
|
latest_check_time = serializers.DateTimeField(source='get_latest_check_time', read_only=True)
|
||||||
|
latest_response_time = serializers.FloatField(source='get_latest_response_time', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Service
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceCheckInSerializer(serializers.Serializer):
|
||||||
|
"""客户端上报数据序列化器"""
|
||||||
|
service_name = serializers.CharField(max_length=200)
|
||||||
|
host = serializers.CharField(max_length=255)
|
||||||
|
port = serializers.IntegerField(required=False, allow_null=True)
|
||||||
|
check_type = serializers.CharField(max_length=50, default='tcp')
|
||||||
|
status = serializers.ChoiceField(choices=Service.STATUS_CHOICES)
|
||||||
|
response_time = serializers.FloatField(required=False, allow_null=True)
|
||||||
|
message = serializers.CharField(required=False, allow_blank=True)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""创建或更新服务记录"""
|
||||||
|
service_name = validated_data['service_name']
|
||||||
|
host = validated_data['host']
|
||||||
|
port = validated_data.get('port')
|
||||||
|
check_type = validated_data.get('check_type', 'tcp')
|
||||||
|
status = validated_data['status']
|
||||||
|
response_time = validated_data.get('response_time')
|
||||||
|
message = validated_data.get('message', '')
|
||||||
|
|
||||||
|
logger.info(f"收到服务上报: {service_name} ({host}:{port}), 状态: {status}")
|
||||||
|
|
||||||
|
# 获取或创建默认分组
|
||||||
|
group_name = 'Default'
|
||||||
|
group, created = ServiceGroup.objects.get_or_create(name=group_name)
|
||||||
|
if created:
|
||||||
|
logger.info(f"创建默认分组: {group_name}")
|
||||||
|
|
||||||
|
# 获取或创建服务
|
||||||
|
service, created = Service.objects.get_or_create(
|
||||||
|
name=service_name,
|
||||||
|
host=host,
|
||||||
|
port=port,
|
||||||
|
check_type=check_type,
|
||||||
|
defaults={'group': group}
|
||||||
|
)
|
||||||
|
|
||||||
|
if created:
|
||||||
|
logger.info(f"创建新服务: {service_name} ({host}:{port})")
|
||||||
|
|
||||||
|
# 创建检测记录
|
||||||
|
record = ServiceCheckRecord.objects.create(
|
||||||
|
service=service,
|
||||||
|
status=status,
|
||||||
|
response_time=response_time,
|
||||||
|
message=message
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"保存检测记录: {service_name}, 状态: {status}, 响应时间: {response_time}ms")
|
||||||
|
|
||||||
|
return {
|
||||||
|
'service_id': service.id,
|
||||||
|
'record_id': record.id
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class StatusSummarySerializer(serializers.Serializer):
|
||||||
|
"""状态摘要序列化器"""
|
||||||
|
total_services = serializers.IntegerField()
|
||||||
|
up_services = serializers.IntegerField()
|
||||||
|
down_services = serializers.IntegerField()
|
||||||
|
unknown_services = serializers.IntegerField()
|
||||||
|
uptime_percentage = serializers.FloatField()
|
||||||
130
status/templates/status/api_docs.html
Normal file
130
status/templates/status/api_docs.html
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{% extends 'status/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}API说明{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="bg-white rounded-xl p-6 card-shadow mb-6">
|
||||||
|
<h1 class="text-2xl font-bold text-gray-800 mb-4">API接口说明</h1>
|
||||||
|
<p class="text-gray-600 mb-6">本系统提供以下RESTful API接口,用于服务状态的上报和查询。</p>
|
||||||
|
|
||||||
|
<div class="mb-8">
|
||||||
|
<h2 class="text-xl font-bold text-gray-800 mb-4">认证方式</h2>
|
||||||
|
<div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-4">
|
||||||
|
<p class="text-blue-700">目前所有API接口均无需认证,可直接访问。后续版本可能会添加认证机制。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-8">
|
||||||
|
<h2 class="text-xl font-bold text-gray-800 mb-4">API端点列表</h2>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">POST /api/checkin/ - 客户端上报接口</h3>
|
||||||
|
<p class="text-gray-600 mb-3">用于客户端上报服务状态信息。如果服务不存在,系统会自动创建。</p>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<h4 class="font-medium text-gray-700 mb-2">请求体示例:</h4>
|
||||||
|
<pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto"><code>{
|
||||||
|
"service_name": "Web服务",
|
||||||
|
"host": "192.168.1.100",
|
||||||
|
"port": 80,
|
||||||
|
"check_type": "http",
|
||||||
|
"status": "UP",
|
||||||
|
"response_time": 120.5,
|
||||||
|
"message": "连接成功"
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="font-medium text-gray-700 mb-2">响应示例:</h4>
|
||||||
|
<pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto"><code>{
|
||||||
|
"code": 200,
|
||||||
|
"message": "服务状态已更新",
|
||||||
|
"service_id": 1
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">GET /api/services/ - 服务列表查询接口</h3>
|
||||||
|
<p class="text-gray-600 mb-3">获取所有服务的列表及其最新状态。</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="font-medium text-gray-700 mb-2">响应示例:</h4>
|
||||||
|
<pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto"><code>[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Web服务",
|
||||||
|
"host": "192.168.1.100",
|
||||||
|
"port": 80,
|
||||||
|
"check_type": "http",
|
||||||
|
"group": "Web服务组",
|
||||||
|
"description": "公司主网站",
|
||||||
|
"latest_status": "UP",
|
||||||
|
"latest_check_time": "2025-06-15T10:30:00Z",
|
||||||
|
"latest_response_time": 120.5
|
||||||
|
}
|
||||||
|
]</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">GET /api/services/{id}/history/ - 服务历史记录查询接口</h3>
|
||||||
|
<p class="text-gray-600 mb-3">获取指定服务的历史检测记录。</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="font-medium text-gray-700 mb-2">响应示例:</h4>
|
||||||
|
<pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto"><code>{
|
||||||
|
"count": 1,
|
||||||
|
"total_pages": 1,
|
||||||
|
"current_page": 1,
|
||||||
|
"page_size": 20,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"service": 1,
|
||||||
|
"status": "UP",
|
||||||
|
"response_time": 120.5,
|
||||||
|
"message": "连接成功",
|
||||||
|
"check_time": "2025-06-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">GET /api/status-summary/ - 状态摘要查询接口</h3>
|
||||||
|
<p class="text-gray-600 mb-3">获取所有服务的状态摘要统计信息。</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="font-medium text-gray-700 mb-2">响应示例:</h4>
|
||||||
|
<pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto"><code>{
|
||||||
|
"total_services": 10,
|
||||||
|
"up_count": 8,
|
||||||
|
"down_count": 1,
|
||||||
|
"unknown_count": 1
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h2 class="text-xl font-bold text-gray-800 mb-4">状态码说明</h2>
|
||||||
|
<ul class="list-disc pl-5 text-gray-600 space-y-1">
|
||||||
|
<li><strong>UP</strong>: 服务正常运行</li>
|
||||||
|
<li><strong>DOWN</strong>: 服务不可用</li>
|
||||||
|
<li><strong>UNKNOWN</strong>: 服务状态未知</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h2 class="text-xl font-bold text-gray-800 mb-4">检测类型说明</h2>
|
||||||
|
<ul class="list-disc pl-5 text-gray-600 space-y-1">
|
||||||
|
<li><strong>http</strong>: HTTP检测</li>
|
||||||
|
<li><strong>https</strong>: HTTPS检测</li>
|
||||||
|
<li><strong>tcp</strong>: TCP端口检测</li>
|
||||||
|
<li><strong>ping</strong>: PING检测</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -56,9 +56,17 @@
|
|||||||
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold">服务状态监控</h1>
|
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold">服务状态监控</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<i class="fas fa-refresh animate-spin mr-2"></i>
|
<a href="/admin/" class="text-white hover:text-gray-200 transition-colors">
|
||||||
<span id="last-updated" class="text-sm md:text-base">最后更新: 加载中...</span>
|
<i class="fas fa-cog mr-1"></i> 管理后台
|
||||||
</div>
|
</a>
|
||||||
|
<a href="/api-docs/" class="text-white hover:text-gray-200 transition-colors">
|
||||||
|
<i class="fas fa-book mr-1"></i> API说明
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<i class="fas fa-refresh animate-spin mr-2"></i>
|
||||||
|
<span id="last-updated" class="text-sm md:text-base">最后更新: 加载中...</span>
|
||||||
|
</div>
|
||||||
<div class="mt-4 md:mt-0">
|
<div class="mt-4 md:mt-0">
|
||||||
<a href="/services/" class="bg-white text-primary px-4 py-2 rounded-lg font-medium hover:bg-gray-100 transition-colors">
|
<a href="/services/" class="bg-white text-primary px-4 py-2 rounded-lg font-medium hover:bg-gray-100 transition-colors">
|
||||||
<i class="fas fa-list mr-2"></i> 查看所有服务
|
<i class="fas fa-list mr-2"></i> 查看所有服务
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ urlpatterns = [
|
|||||||
path('api/services/', views.api_services, name='api_services'),
|
path('api/services/', views.api_services, name='api_services'),
|
||||||
path('api/services/<int:service_id>/history/', views.api_service_history, name='api_service_history'),
|
path('api/services/<int:service_id>/history/', views.api_service_history, name='api_service_history'),
|
||||||
path('api/status-summary/', views.api_status_summary, name='api_status_summary'),
|
path('api/status-summary/', views.api_status_summary, name='api_status_summary'),
|
||||||
|
|
||||||
|
# API文档页面
|
||||||
|
path('api-docs/', views.api_docs, name='api_docs'),
|
||||||
]
|
]
|
||||||
|
|
||||||
logger.info("URL路由配置已加载")
|
logger.info("URL路由配置已加载")
|
||||||
@@ -217,3 +217,8 @@ def api_status_summary(request):
|
|||||||
"""获取全局状态摘要(如:总共服务数、正常数、异常数)"""
|
"""获取全局状态摘要(如:总共服务数、正常数、异常数)"""
|
||||||
summary = get_status_summary()
|
summary = get_status_summary()
|
||||||
return JsonResponse(summary)
|
return JsonResponse(summary)
|
||||||
|
|
||||||
|
# API文档页面
|
||||||
|
def api_docs(request):
|
||||||
|
"""API文档页面"""
|
||||||
|
return render(request, 'status/api_docs.html')
|
||||||
|
|||||||
Binary file not shown.
@@ -20,4 +20,5 @@ from django.urls import path, include
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('', include('status.urls')),
|
path('', include('status.urls')),
|
||||||
|
path('api/', include('status.api_urls')),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user