import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 项目根路径
SECRET_KEY = '00s&54!s7c47gi(^97x!ep$ywfy8t3kj=%woay%u^cnhn^mqmz' # 秘钥,自动生成的,django中涉及到加密的都需要使用到
DEBUG = True # 是否为调试模式,开启可以在浏览器中看到错误信息,访问不存在的页面也会显示可访问的路由有哪些
ALLOWED_HOSTS = ['*'] # 允许项目部署的地址(后期项目上线,这里写服务器的地址),debug是False,这个必须加,不加就报错
INSTALLED_APPS = [ # 所有的app
'django.contrib.admin', # 后台管理admin
'django.contrib.auth', # 权限,6个表
'django.contrib.contenttypes',
'django.contrib.sessions', # session认证相关
'django.contrib.messages', # 消息框架
'django.contrib.staticfiles', # 静态文件
'app01.apps.App01Config',
'rest_framework'
]
MIDDLEWARE = [ # 中间件
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', # session相关
'django.middleware.common.CommonMiddleware', # 路由匹配不成功时把路由加/再匹配,如果添加后匹配成功,将该请求重定向到带/的地址
'django.middleware.csrf.CsrfViewMiddleware', # csrf相关
'django.contrib.auth.middleware.AuthenticationMiddleware', # 认证相关
'django.contrib.messages.middleware.MessageMiddleware', # 消息框架
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'drf_day08.urls' # 根路由
TEMPLATES = [...]# 模板相关
WSGI_APPLICATION = 'drf_day08.wsgi.application' # 后期项目项目上线,uwsgi运行这个application,测试阶段使用manage.py 运行项目
DATABASES = { # 数据库相关
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
AUTH_PASSWORD_VALIDATORS = [...] # auth的认证相关
# 国际化
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/' # 静态文件相关
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # 所有的自增主键都用BigAutoField
"""
内置的过滤类只能通过search=xxx搜索,不能够指定name=xxx&price=99
想要实现可以使用第三方模块或者自定义过滤类
"""
# 第三方:django-filter
1. pip install django-filter
2. 在视图类中配置:filter_backends = [DjangoFilterBackend]
3. 配置搜索的字段:filterset_fields = ['name', 'price']
4. 支持的搜索方式:http://127.0.0.1:8000/books/?name=红楼梦&price=99
5. 默认为精准搜索,条件使并且的关系
# 自定义过滤类
1. 写一个类,继承BaseFilterBackend
2. 重写filter_queryset方法
3. 在方法中过滤数据,并返回queryset对象
def filter_queryset(self, request, queryset, view):
name = request.query_params.get('name')
price = request.query_params.get('price')
return queryset.filter(name__icontains=name,price__icontains=price)
4. 配置在视图类上:filter_backends = [类名]
"""多个过滤类和排序类可以共用,filter_backends=[],可以配置多个,执行顺序是从做往右,所以,放在最左侧的尽量先过滤掉大部分数据"""
drf中无论在三大认证还是视图类的方法中执行,只要报错就会被捕获然后执行一个函数
只要出现异常被捕获了,就执行了drf中内置的配置文件中的配置:‘EXCEPTION_HANDLER’: ‘rest_framework.views.exception_handler’,
只需要自己写一个函数,配置在配置文件中,以后出了异常,就会走我们写的函数
def exception_comment(exc, context):
"""报错后记录日志"""
request = context.get('request') # 当此请求的request
try:
username = request.user.username
except:
username = '没有登录'
ctime = time.time()
path = request.path
method_type = request.method
print('%s用户,在%s时间,访问%s接口,通过%s请求访问,出了错误:%s' % (username, str(ctime), path, method_type, str(exc)))
# 后期以上的代码要写到日志中
response = exception_handler(exc, context) # 内置的异常处理函数,只处理了drf自己的异常
if response: # 如果有值,说明是drf自己的异常,错误已经被处理了
return Response({'code': 800, 'msg': 'drf错误:%s' % response.data.get("detail", "未知错误")})
else: # 如果没有值,说明不是drf的错误,是django或代码的错误
return Response({'code': 900, 'msg': '系统错误:%s' % str(exc)})
# 在配置文件中配置
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'app01.views.exception_comment',}
接口编写完成后,需要编写接口文档给前端的人使用
接口文档中一般需要有:请求地址、请求方式、支持的编码格式、请求参数、返回格式示例
1. 下载coreapi模块:pip install coreapi
2. 路由中配置
from rest_framework.documentation import include_docs_urls
urlpatterns = [
path('docs/', include_docs_urls(title='接口文档')),
]
3. 在配置文件中配置
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}
3. 在视图类中添加注释
class BookView(ModelViewSet):
"""
list:
返回所有图书信息
create:
添加一本图书
"""
"""接口文档中的说明需要在序列化类中的字段属性help_text上添加"""
from django.db.models import Q
from rest_framework.filters import BaseFilterBackend
class SearchFilter_app01(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
name = request.query_params.get('name', None)
price = request.query_params.get('price', None)
if name is None and price is None:
return queryset
elif name is None:
return queryset.filter(Q(price__icontains=price))
elif price is None:
return queryset.filter(Q(name__icontains=name))
return queryset.filter(Q(name__icontains=name) | Q(price__icontains=price))
from rest_framework.views import exception_handler
from rest_framework.response import Response
def exception_comment(exc, context):
response = exception_handler(exc, context)
if response:
return Response({'code': 800, 'msg': 'drf错误:%s' % response.data.get("detail", "未知错误")})
else:
return Response({'code': 900, 'msg': '系统错误:%s' % str(exc)})