调整为http相应状态
This commit is contained in:
parent
d748a8dd59
commit
746c8874c4
|
@ -0,0 +1,2 @@
|
|||
|
||||
NAME_OR_PASSWORD_WRONG = '账户名或密码错误'
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
from rest_framework.exceptions import ParseError, ValidationError
|
||||
from django.shortcuts import render
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
|
@ -7,8 +8,9 @@ from django.contrib.auth import authenticate, login, logout
|
|||
from rest_framework.generics import CreateAPIView
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
|
||||
from apps.auth1.serializers import LoginSerializer
|
||||
from apps.utils.response import FailResponse, SuccessResponse
|
||||
|
||||
# Create your views here.
|
||||
|
||||
class TokenBlackView(APIView):
|
||||
|
@ -42,8 +44,8 @@ class LoginView(CreateAPIView):
|
|||
password = vdata.get('password'))
|
||||
if user is not None:
|
||||
login(request, user)
|
||||
return SuccessResponse()
|
||||
return FailResponse(msg='账户或密码错误')
|
||||
return Response()
|
||||
raise ParseError('账户名或密码错误', 'username_or_password_wrong')
|
||||
|
||||
class LogoutView(APIView):
|
||||
authentication_classes = []
|
||||
|
@ -57,4 +59,4 @@ class LogoutView(APIView):
|
|||
退出登录
|
||||
"""
|
||||
logout(request)
|
||||
return SuccessResponse()
|
||||
return Response()
|
|
@ -10,7 +10,7 @@ import os
|
|||
from rest_framework import serializers, status
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from apps.utils.response import SuccessResponse
|
||||
from rest_framework.exceptions import NotFound
|
||||
# Create your views here.
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ class ServerInfoView(APIView):
|
|||
ret['disk']['total'] = round(disk.total/1024/1024/1024, 2)
|
||||
ret['disk']['used'] = round(disk.used/1024/1024/1024, 2)
|
||||
ret['disk']['percent'] = disk.percent
|
||||
return SuccessResponse(ret)
|
||||
return Response(ret)
|
||||
|
||||
|
||||
def get_file_list(file_path):
|
||||
|
@ -101,7 +101,7 @@ class LogView(APIView):
|
|||
"filepath": filepath,
|
||||
"size": round(fsize/1000, 1)
|
||||
})
|
||||
return SuccessResponse(data=logs)
|
||||
return Response(logs)
|
||||
|
||||
|
||||
class LogDetailView(APIView):
|
||||
|
@ -117,4 +117,5 @@ class LogDetailView(APIView):
|
|||
data = f.read()
|
||||
return Response(data)
|
||||
except:
|
||||
return Response('未找到', status=status.HTTP_404_NOT_FOUND)
|
||||
raise NotFound('不存在该日志')
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# 自定义的错误码
|
||||
from rest_framework.exceptions import ValidationError
|
|
@ -1,13 +1,10 @@
|
|||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.hashers import check_password, make_password
|
||||
from django.db import transaction
|
||||
from django_celery_beat.models import (CrontabSchedule, IntervalSchedule,
|
||||
PeriodicTask)
|
||||
from django_celery_results.models import TaskResult
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.exceptions import ParseError, ValidationError
|
||||
from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin,
|
||||
ListModelMixin, RetrieveModelMixin)
|
||||
from rest_framework.parsers import (JSONParser,
|
||||
|
@ -17,9 +14,9 @@ from rest_framework.response import Response
|
|||
from rest_framework.views import APIView
|
||||
|
||||
from apps.utils.mixins import (CustomCreateModelMixin)
|
||||
from django.conf import settings
|
||||
from apps.utils.permission import get_user_perms_map
|
||||
from apps.utils.queryset import get_child_queryset2
|
||||
from apps.utils.response import FailResponse, SuccessResponse
|
||||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||||
from server.celery import app as celery_app
|
||||
from .filters import UserFilter
|
||||
|
@ -32,8 +29,6 @@ from .serializers import (DeptCreateUpdateSerializer, DeptSerializer, DictCreate
|
|||
UserCreateSerializer, UserListSerializer, UserPostCreateSerializer,
|
||||
UserPostSerializer, UserUpdateSerializer)
|
||||
|
||||
logger = logging.getLogger('log')
|
||||
|
||||
|
||||
# logger.info('请求成功! response_code:{};response_headers:{};
|
||||
# response_body:{}'.format(response_code, response_headers, response_body[:251]))
|
||||
|
@ -80,7 +75,7 @@ class PTaskViewSet(CustomModelViewSet):
|
|||
obj = self.get_object()
|
||||
obj.enabled = False if obj.enabled else True
|
||||
obj.save()
|
||||
return SuccessResponse()
|
||||
return Response()
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, request, *args, **kwargs):
|
||||
|
@ -99,7 +94,7 @@ class PTaskViewSet(CustomModelViewSet):
|
|||
**interval_, defaults=interval_)
|
||||
data['interval'] = interval.id
|
||||
except:
|
||||
raise ValidationError('时间策略有误')
|
||||
raise ParseError('时间策略有误', 'schedule_wrong')
|
||||
if timetype == 'crontab' and crontab_:
|
||||
data['interval'] = None
|
||||
try:
|
||||
|
@ -108,11 +103,11 @@ class PTaskViewSet(CustomModelViewSet):
|
|||
**crontab_, defaults=crontab_)
|
||||
data['crontab'] = crontab.id
|
||||
except:
|
||||
raise ValidationError('时间策略有误')
|
||||
raise ParseError('时间策略有误', 'schedule_wrong')
|
||||
serializer = self.get_serializer(data=data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return SuccessResponse()
|
||||
return Response()
|
||||
|
||||
@transaction.atomic
|
||||
def update(self, request, *args, **kwargs):
|
||||
|
@ -133,7 +128,7 @@ class PTaskViewSet(CustomModelViewSet):
|
|||
**interval_, defaults=interval_)
|
||||
data['interval'] = interval.id
|
||||
except:
|
||||
raise ValidationError('时间策略有误')
|
||||
raise ParseError('时间策略有误', 'schedule_wrong')
|
||||
if timetype == 'crontab' and crontab_:
|
||||
data['interval'] = None
|
||||
try:
|
||||
|
@ -144,12 +139,12 @@ class PTaskViewSet(CustomModelViewSet):
|
|||
**crontab_, defaults=crontab_)
|
||||
data['crontab'] = crontab.id
|
||||
except:
|
||||
raise ValidationError('时间策略有误')
|
||||
raise ParseError('时间策略有误', 'schedule_wrong')
|
||||
instance = self.get_object()
|
||||
serializer = self.get_serializer(instance, data=data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return SuccessResponse()
|
||||
return Response()
|
||||
|
||||
|
||||
class PTaskResultViewSet(ListModelMixin, RetrieveModelMixin, CustomGenericViewSet):
|
||||
|
@ -310,7 +305,7 @@ class UserViewSet(CustomModelViewSet):
|
|||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save(password=password)
|
||||
return SuccessResponse(data=serializer.data)
|
||||
return Response(data=serializer.data)
|
||||
|
||||
@action(methods=['put'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def password(self, request, pk=None):
|
||||
|
@ -326,11 +321,11 @@ class UserViewSet(CustomModelViewSet):
|
|||
if new_password1 == new_password2:
|
||||
user.set_password(new_password2)
|
||||
user.save()
|
||||
return SuccessResponse()
|
||||
return Response()
|
||||
else:
|
||||
return FailResponse(msg='新密码两次输入不一致!')
|
||||
raise ParseError('新密码两次输入不一致!', 'password_not_same')
|
||||
else:
|
||||
return FailResponse(msg='旧密码错误!')
|
||||
raise ValidationError('旧密码错误!', 'old_password_wrong')
|
||||
|
||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def info(self, request, pk=None):
|
||||
|
@ -348,7 +343,7 @@ class UserViewSet(CustomModelViewSet):
|
|||
'avatar': user.avatar,
|
||||
'perms': perms,
|
||||
}
|
||||
return SuccessResponse(data)
|
||||
return Response(data)
|
||||
|
||||
|
||||
class FileViewSet(CustomCreateModelMixin, RetrieveModelMixin, ListModelMixin, CustomGenericViewSet):
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.shortcuts import render
|
||||
from apps.utils.dahua import dhClient
|
||||
from apps.utils.xunxi import xxClient
|
||||
from rest_framework.response import Response
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
from typing import Tuple
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404
|
||||
from server.settings import myLogger
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.views import set_rollback
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import traceback
|
||||
|
||||
class MyError(exceptions.ParseError):
|
||||
"""自定义业务异常
|
||||
"""
|
||||
|
||||
def __init__(self, error:Tuple[str, str]=(), detail=None, code=None):
|
||||
if error:
|
||||
code, detail = error
|
||||
super().__init__(detail, code)
|
||||
|
||||
def custom_exception_hander(exc, context):
|
||||
"""
|
||||
自定义异常处理
|
||||
"""
|
||||
if isinstance(exc, Http404):
|
||||
exc = exceptions.NotFound()
|
||||
elif isinstance(exc, PermissionDenied):
|
||||
exc = exceptions.PermissionDenied()
|
||||
|
||||
if isinstance(exc, exceptions.APIException):
|
||||
headers = {}
|
||||
if getattr(exc, 'auth_header', None):
|
||||
headers['WWW-Authenticate'] = exc.auth_header
|
||||
if getattr(exc, 'wait', None):
|
||||
headers['Retry-After'] = '%d' % exc.wait
|
||||
|
||||
if isinstance(exc.detail, (list, dict)):
|
||||
data = {'err_detail':exc.detail}
|
||||
data['err_codes'] = exc.get_codes()
|
||||
else:
|
||||
data = {'err_msg': exc.detail, 'err_code':exc.get_codes()}
|
||||
|
||||
set_rollback()
|
||||
return Response(data, status=exc.status_code, headers=headers)
|
||||
# 未处理的异常记录日志
|
||||
myLogger.error(traceback.format_exc())
|
||||
return Response(data={'err_code':'server_error', 'err_msg':'服务器错误'}, status=500)
|
|
@ -1,8 +1,9 @@
|
|||
from django.db import models
|
||||
import django.utils.timezone as timezone
|
||||
from django.db import models
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
from apps.utils.snowflake import worker
|
||||
from apps.utils.snowflake import idWorker
|
||||
|
||||
|
||||
# 自定义软删除查询基类
|
||||
|
||||
|
@ -55,7 +56,7 @@ class BaseModel(models.Model):
|
|||
"""
|
||||
基本表
|
||||
"""
|
||||
id = models.CharField(max_length=20, primary_key=True, default=worker.get_id, editable=False, verbose_name='主键ID', help_text='主键ID')
|
||||
id = models.CharField(max_length=20, primary_key=True, default=idWorker.get_id, editable=False, verbose_name='主键ID', help_text='主键ID')
|
||||
create_time = models.DateTimeField(
|
||||
default=timezone.now, verbose_name='创建时间', help_text='创建时间')
|
||||
update_time = models.DateTimeField(
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.db.models.query import QuerySet
|
|||
|
||||
def get_user_perms_map(user):
|
||||
"""
|
||||
获取权限列表,可用redis存取
|
||||
获取权限字典,可用redis存取
|
||||
"""
|
||||
user_perms_map = {}
|
||||
if user.is_superuser:
|
||||
|
@ -44,7 +44,7 @@ class RbacPermission(BasePermission):
|
|||
:return:
|
||||
"""
|
||||
if not hasattr(view, 'perms_map'):
|
||||
return False
|
||||
return True
|
||||
user_perms_map = cache.get('perms_' + request.user.id, None)
|
||||
if user_perms_map is None:
|
||||
user_perms_map = get_user_perms_map(request.user)
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
import traceback
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
from rest_framework.views import exception_handler
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status as drf_status
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('log')
|
||||
|
||||
def custome_exception_hander(exc, context):
|
||||
"""
|
||||
自定义异常处理
|
||||
"""
|
||||
res = exception_handler(exc, context)
|
||||
if res:
|
||||
return res
|
||||
else:
|
||||
"""
|
||||
日志记录
|
||||
"""
|
||||
logger.error(traceback.format_exc())
|
||||
return None
|
||||
|
||||
class FitJSONRenderer(JSONRenderer):
|
||||
"""
|
||||
自行封装的渲染器
|
||||
"""
|
||||
|
||||
def render(self, data, accepted_media_type=None, renderer_context=None):
|
||||
"""
|
||||
如果使用这个render,
|
||||
普通的response将会被包装成:
|
||||
{"code":200000,"data":"X","msg":"X"}
|
||||
这样的结果
|
||||
使用方法:
|
||||
- 全局
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_RENDERER_CLASSES': ('utils.response.FitJSONRenderer', ),
|
||||
}
|
||||
- 局部
|
||||
class UserCountView(APIView):
|
||||
renderer_classes = [FitJSONRenderer]
|
||||
|
||||
:param data:
|
||||
:param accepted_media_type:
|
||||
:param renderer_context:
|
||||
:return: {"code":200,"data":"X","msg":"X"}
|
||||
"""
|
||||
response_body = dict(success=True, code=200000, msg='请求成功', data=None)
|
||||
response = renderer_context.get("response")
|
||||
status_code = response.status_code
|
||||
if isinstance(data, dict) and data.keys() == response_body.keys():
|
||||
response_body = data
|
||||
else:
|
||||
# 处理drf格式的返回数据
|
||||
if status_code >= 400: # 如果http响应异常
|
||||
response_body = dict(success=False, code=400000, msg='请求失败', data=None)
|
||||
response_body['data'] = data # data里是详细异常信息
|
||||
response_body['code'] = status_code*1000
|
||||
prefix = ""
|
||||
if isinstance(data, dict):
|
||||
prefix = list(data.keys())[0]
|
||||
data = data[prefix]
|
||||
if isinstance(data, list):
|
||||
data = data[0]
|
||||
|
||||
if prefix != 'detail':
|
||||
response_body['msg'] = prefix + str(data) # 取一部分放入msg,方便前端alert
|
||||
else:
|
||||
response_body['data'] = data
|
||||
renderer_context.get("response").status_code = 200 # 统一成200响应, 可用body里code区分业务异常
|
||||
return super(FitJSONRenderer, self).render(response_body, accepted_media_type, renderer_context)
|
||||
|
||||
|
||||
class SuccessResponse(Response):
|
||||
def __init__(self, data=None, msg='请求成功', code=200000, status=None, template_name=None, headers=None, exception=False, content_type=None):
|
||||
std_data = dict(success=True, code=code, msg=msg, data=data)
|
||||
super().__init__(std_data, status, template_name, headers, exception, content_type)
|
||||
|
||||
class FailResponse(Response):
|
||||
def __init__(self, msg='请求失败', data=None, code=400000, status=400, template_name=None, headers=None, exception=False, content_type=None):
|
||||
std_data = dict(success=False, code=code, msg=msg, data=data)
|
||||
super().__init__(std_data, status, template_name, headers, exception, content_type)
|
|
@ -3,7 +3,7 @@ from rest_framework import serializers
|
|||
from django_restql.mixins import DynamicFieldsMixin
|
||||
|
||||
class PkSerializer(serializers.Serializer):
|
||||
pks = serializers.ListField(child=serializers.IntegerField(min_value=1), label="主键ID列表")
|
||||
pks = serializers.ListField(child=serializers.CharField(max_length=20), label="主键ID列表")
|
||||
|
||||
class GenSignatureSerializer(serializers.Serializer):
|
||||
path = serializers.CharField(label="图片地址")
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
# https://github.com/twitter-archive/snowflake/blob/snowflake-2010/src/main/scala/com/twitter/service/snowflake/IdWorker.scala
|
||||
|
||||
import time
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
# logger = logging.getLogger('log')
|
||||
from server.settings import SNOW_DATACENTER_ID, SNOW_WORKER_ID
|
||||
|
||||
class InvalidSystemClock(Exception):
|
||||
"""
|
||||
|
@ -76,7 +73,6 @@ class IdWorker(object):
|
|||
|
||||
# 时钟回拨
|
||||
if timestamp < self.last_timestamp:
|
||||
# logger.error('clock is moving backwards. Rejecting requests until {}'.format(self.last_timestamp))
|
||||
raise InvalidSystemClock
|
||||
|
||||
if timestamp == self.last_timestamp:
|
||||
|
@ -101,7 +97,7 @@ class IdWorker(object):
|
|||
timestamp = self._gen_timestamp()
|
||||
return timestamp
|
||||
|
||||
worker = IdWorker(settings.SNOW_DATACENTER_ID, settings.SNOW_WORKER_ID)
|
||||
idWorker = IdWorker(SNOW_DATACENTER_ID, SNOW_WORKER_ID)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(worker.get_id())
|
||||
print(idWorker.get_id())
|
|
@ -3,7 +3,8 @@ import os
|
|||
import cv2
|
||||
from server.settings import BASE_DIR
|
||||
import numpy as np
|
||||
from .response import FailResponse, SuccessResponse
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.exceptions import ParseError
|
||||
from apps.utils.viewsets import CustomGenericViewSet
|
||||
from apps.utils.mixins import CustomCreateModelMixin
|
||||
from apps.utils.serializers import GenSignatureSerializer
|
||||
|
@ -42,6 +43,6 @@ class SignatureViewSet(CustomCreateModelMixin, CustomGenericViewSet):
|
|||
ext = os.path.splitext(path)
|
||||
new_path = ext[0] + '.png'
|
||||
cv2.imwrite(new_path, image)
|
||||
return SuccessResponse({'path': new_path.replace(BASE_DIR, '')})
|
||||
return Response({'path': new_path.replace(BASE_DIR, '')})
|
||||
except:
|
||||
return FailResponse(msg='签名照处理失败,请重新上传')
|
||||
raise ParseError('签名照处理失败,请重新上传')
|
||||
|
|
|
@ -4,9 +4,10 @@ from rest_framework.decorators import action
|
|||
from apps.utils.mixins import CustomCreateModelMixin, CustomDestoryModelMixin, CustomUpdateModelMixin, OptimizationMixin
|
||||
from apps.utils.permission import RbacDataMixin, RbacPermission
|
||||
from apps.utils.serializers import PkSerializer
|
||||
from apps.utils.response import FailResponse, SuccessResponse
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.mixins import DestroyModelMixin, RetrieveModelMixin, ListModelMixin
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
|
||||
class CustomGenericViewSet(GenericViewSet):
|
||||
|
@ -59,9 +60,9 @@ class CustomModelViewSet(OptimizationMixin, CustomCreateModelMixin
|
|||
pks = request_data.get('pks',None)
|
||||
if pks:
|
||||
self.get_queryset().filter(id__in=pks).delete(update_by=request.user)
|
||||
return SuccessResponse()
|
||||
return Response()
|
||||
else:
|
||||
return FailResponse(msg="未获取到pks字段")
|
||||
raise ValidationError("未获取到pks字段")
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
|
|||
from datetime import datetime, timedelta
|
||||
import os
|
||||
from . import conf
|
||||
from server.conf import DATABASES, XX_ENABLED, XX_LICENCE
|
||||
import logging
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
@ -164,10 +164,10 @@ REST_FRAMEWORK = {
|
|||
'rest_framework.permissions.IsAuthenticated',
|
||||
'apps.utils.permission.RbacPermission'
|
||||
],
|
||||
'DEFAULT_RENDERER_CLASSES': [
|
||||
'apps.utils.response.FitJSONRenderer',
|
||||
'rest_framework.renderers.BrowsableAPIRenderer'
|
||||
],
|
||||
# 'DEFAULT_RENDERER_CLASSES': [
|
||||
# 'apps.utils.response.FitJSONRenderer',
|
||||
# 'rest_framework.renderers.BrowsableAPIRenderer'
|
||||
# ],
|
||||
'DEFAULT_FILTER_BACKENDS': [
|
||||
'django_filters.rest_framework.DjangoFilterBackend',
|
||||
'rest_framework.filters.SearchFilter',
|
||||
|
@ -179,7 +179,7 @@ REST_FRAMEWORK = {
|
|||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
|
||||
'UNAUTHENTICATED_USER': None,
|
||||
'UNAUTHENTICATED_TOKEN': None,
|
||||
'EXCEPTION_HANDLER': 'apps.utils.response.custome_exception_hander',
|
||||
'EXCEPTION_HANDLER': 'apps.utils.exceptions.custom_exception_hander',
|
||||
}
|
||||
# simplejwt配置
|
||||
SIMPLE_JWT = {
|
||||
|
@ -302,6 +302,8 @@ LOGGING = {
|
|||
},
|
||||
}
|
||||
}
|
||||
# 实例化myLogger
|
||||
myLogger = logging.getLogger('log')
|
||||
|
||||
# 大华ICC平台
|
||||
DAHUA_ENABLED = conf.DAHUA_ENABLED
|
||||
|
|
|
@ -37,6 +37,7 @@ urlpatterns = [
|
|||
# django后台
|
||||
path('django/doc/', include('django.contrib.admindocs.urls')),
|
||||
path('django/', admin.site.urls),
|
||||
path('api-auth/', include('rest_framework.urls')),
|
||||
|
||||
# api
|
||||
path('', include('apps.auth1.urls')),
|
||||
|
@ -47,13 +48,14 @@ urlpatterns = [
|
|||
path('', include('apps.utils.urls')),
|
||||
|
||||
|
||||
|
||||
# api文档
|
||||
path('api/docs/', include_docs_urls(title="接口文档", authentication_classes=[], permission_classes=[])),
|
||||
path('api/swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||
path('api/redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
|
||||
|
||||
# 前端页面入口
|
||||
path('',TemplateView.as_view(template_name="index.html"))
|
||||
path('',TemplateView.as_view(template_name="index.html")),
|
||||
] + \
|
||||
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + \
|
||||
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
|
Loading…
Reference in New Issue