本周是第十周,本周学习了django框架前后端分离相关知识点,REST框架,网络API接口,以及性能调试,以下是知识点回顾与整理:
1.11本周总结
-
版本控制补充 - 回退
- git reset --hard versionid / head^
- git reflog 记录
-
django日志配置 - settings.py
日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL
ELK - ElasticSearch Logstash Kibana - 日志处理平台
# settings.py,以下配置为日志debug级别打印至控制台 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db': { 'handlers': ['console', ], 'level': 'DEBUG', }, }, }
-
django-debug-toolbar - django调试工具
debug-debug-toolbar可查看数据请求的时长、数据库查询语句等
配置:settings.py与urls.py
# 首先安装第三方库:pip install django-debug-toolbar # settings.py INSTALLED_APPS = [ ... 'debug_toolbar', ] MIDDLEWARE = [ 'debug_toolbar.middleware.DebugToolbarMiddleware', ] DEBUG_TOOLBAR_CONFIG = { # 引入jQuery库 'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js', # 工具栏是否折叠 'SHOW_COLLAPSED': True, # 是否显示工具栏 'SHOW_TOOLBAR_CALLBACK': lambda x: True, } # urls.py from django.conf import settings from django.urls import include if settings.DEBUG: import debug_toolbar urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
-
性能优化之一,数据库1+N查询问题,是指只需只需用SQL语句查询一次即可出结果,却重复查询多次
方法:利用django的连表查询
- 一对多:select_related()
- 多对多:prefetch_related()
-
django项目前后端分离开发
- 服务器完成核心业务返回json等数据,客服端处理渲染数据与页面
- 优点:
- 提升开发效率
- 增强代码可维护性
- 支持多终端和服务器结构
-
API - Application Programming Interface 应用程序编程接口
网络API - 通过http/https请求请求一个url获得json数据
API接口应围绕实体设计,而不是围绕业务设计,否则后期更改会增加工作量与复杂度
实体 -- 数据 -- 数据接口 -- 网络API(基于http/https)
REST架构 - RESTful API -- 无状态、幂等性
- 幂等性:一次货多次请求某一个资源对于资源本身具有同样的结果
REST - REpresentational State Transfer - 表现层状态转移
rest可以更好的支持水平扩展 - 单机结构 --> 多机结构(分布式集群)
http -- 无连接无状态协议
url -- universal resource locator 统一资源定位符,根据rest架构url设计应使用名词
get -- 查看
post -- 新增
put -- 全更新
patch -- 补丁似的更新
delete -- 删除
-
具体网络API接口项目如下,以房源信息获取为例:
- 首先对rest框架进行安装配置
# rest框架的安装 - pip install djangorestframework # settings.py INSTALLED_APPS = [ ... 'rest_framework', ]
- 其次,序列化房源信息
fields表示需要获取的数据,'__all__'表示获取全部数据,exclude表示排除的数据
# 序列化器,在app文件夹下创建一个serializers.py存放序列化内容,对需要的数据进行序列化 # serializers.py from rest_framework import serializers from common.models import District, Estate, Agent, HouseType, HouseInfo class HouseInfoSerializer(serializers.ModelSerializer): class Meta: model = HouseInfo fields = '__all__' # exclude = ('houseid',)
- CBV视图创建
# view.py from rest_framework.viewsets import ReadOnlyModelViewSet from common.models import HouseInfo from common.serializers import HouseInfoSerializer # CBV基于类的视图创建 class HouseInfoViewSet(ReadOnlyModelViewSet): queryset = HouseInfo.objects.all().select_related('type', 'district', 'estate', 'agent').prefetch_related('tags').order_by('-pubdate') serializer_class = HouseInfoSerializer
- urls.py配置,在app文件夹内 创建一个新的urls.py配置文件,作为单独的配置
# urls.py from django.urls import path from rest_framework.routers import SimpleRouter from common.views import HouseInfoViewSet # 创建一个房源信息的路由 router = SimpleRouter() router.register('houseinfo', HouseInfoViewSet) urlpatterns += router.urls
这时房源的全部信息API接口已经完成,进入http://127.0.0.1:8000/api/houseinfo/ 可获取房源的全部信息
-
设置全局分页查看房源信息,并且限制查询次数每分钟5次
# DRF配置文件 REST_FRAMEWORK = { # 按页码分页 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 5, # 每页最大显示5条数据 # 限流配置 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttling.AnonRateThrottle', ), 'DEFAULT_THROTTLE_RATES': { 'anon': '5/min', # 一分钟访问5次 }, }
-
设置redis缓存,对部分长期不变的信息进行缓存,可减轻数据库负担,提高查询速度,从而提高用户体验
# settings.py # rest缓存配置 REST_FRAMEWORK_EXTENSIONS = { 'DEFAULT_CACHE_RESPONSE_TIMEOUT': 120, # 过期时间 'DEFAULT_USE_CACHE': 'default', 'DEFAULT_OBJECT_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_object_cache_key_func', 'DEFAULT_LIST_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_list_cache_key_func', } # redis缓存配置 CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': [ 'redis://ip address/0', ], 'KEY_PREFIX': 'projcet_name', 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', 'CONNECTION_POOL_KWARGS': { 'max_connections': 512, }, 'PASSWORD': 'your password', } }, }
- 在app文件夹下创建一个utils.py的文件,用于存放app的功能函数等
# utils.py # 对redis存储的缓存前缀进行修改 import re PATTERN = re.compile(r'(\.[0-9a-f]{32})') def make_key(key, key_prefix, version): items = PATTERN.findall(key)[1:] for item in items: key = key.replace(item, '') return '%s:%s:%s' % (key_prefix, version, key)
- 在view.py中添加装饰器,对需要缓存的数据添加装饰器
# view.py class HouseInfoViewSet(CacheResponseMixin,ModelViewSet): ...
-
添加筛选器,对关键字进行筛选,或者对价格进行排序,筛选价格区间等等
# utils.py # 自定义filterset过滤器筛选功能 class HouseInfoFilterSet(django_filters.FilterSet): """自定义FilterSet过滤""" minprice = django_filters.NumberFilter(field_name='price', lookup_expr='gte') maxprice = django_filters.NumberFilter(field_name='price', lookup_expr='lte') keyword = django_filters.CharFilter(method='filter_by_keyword') @staticmethod def filter_by_keyword(queryset, key, value): queryset = queryset.filter(Q(title__contains=value) | Q(detail__contains=value) | Q(street__contains=value)) return queryset
- 其次在views.py文件,房源信息视图类中添加如下内容
# views.py from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter from common.utils import HouseInfoFilterSet class HouseInfoViewSet(ModelViewSet): ... filter_backends = (DjangoFilterBackend, OrderingFilter) filterset_class = HouseInfoFilterSet ordering_fields = ('price', 'area', 'floor') # 排序内容