-
版本控制补充 - 回退(rollback)相当于在git上提交代码后,再对之前提交的代码的版本进行回溯。这个过程中,全程都会被log记录进行记录。所以在回退的时候,查看版本的代码ID就变得尤为重要了,因为我们回退的依据就是这个id。
- 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调试工具
说明:
这个工具是对django框架的调试进行的一个集成化工具。我们可以使用这个工具查看到很多信息。在以下的说明中,我们会使用该工具对数据库那边查询的sql指令进行查看。往往未经优化的sql语句查询都是特别糟糕的。例如产生一加N查询,这样的多个sql查询语句或许会成为整个系统运行的性能瓶颈。为了优化这一点,我们会通过不同的办法来优化sql语句,即用工具查看到的如下语句,然后提高了数据库的查询速度,整个系统也会得到优化。这是木桶效应的一个明显展示。
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语句查询一次即可出结果,却重复查询多次
为了解决这样的1+N查询,我们会用简单的两行代码加入连表查询使得几次不同的查询汇集成同一个查询。这个样子的inner join的查询会大大提高数据库的工作效率。
方法:利用django的连表查询
- 一对多:select_related()
- 多对多:prefetch_related()
-
django项目前后端分离开发
说明:django的前后端开发在之前的总结中已经有过提及。但是之前的框架是“用django框架自动生成数据库表。并且在html中自己写下前端代码。”这样的开发是不科学也是不专业的。在真正的前后端分离的开发中,数据后端是提供业务逻辑和具体数据库的增删改查的操作的业务流程的,而前端是将接受到的端口数据进行进一步渲染处理的工作。
- 服务器完成核心业务返回json等数据,客服端处理渲染数据与页面
- 优点:
- 提升开发效率
- 增强代码可维护性
- 支持多终端和服务器结构
-
API - Application Programming Interface 应用程序编程接口
说明:应用程序的编程接口又称API,在具体的开发过程中,后端会给前端一个应用程序的编程接口来提供业务逻辑和数据库的代码响应支持。
网络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 ModelViewSet from common.models import HouseInfo from common.serializers import HouseInfoSerializer # CBV基于类的视图创建 class HouseInfoViewSet(ModelViewSet): queryset = HouseInfo.objects.all() 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次
说明:对查询次数的限流是有助于网站维护稳定的操作。因为当服务器的http请求到达一个阈值的时候,整个服务器的访问速度会明显下降。而具体的数学模型请参照清华大学数据研究员的数据。因此我们在次数首先对单个用户的访问做出了一定的限制:即在合理的范围内的请求可以发出并且得以应答,在超出我们设置的每分钟五次之后的数据不予发出。
# 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缓存,对部分长期不变的信息进行缓存,可减轻数据库负担,提高查询速度,从而提高用户体验
说明:redis是一个著名的菲关系型数据库。用以缓存我们接收到的各种数据。因此我们使用这个数据库来作为缓存,将可能多次复用且短时间不发生改变的数据使用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中添加装饰器,对需要缓存的数据添加装饰器
```python
# view.py
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
@method_decorator(decorator=cache_page(timeout=300, key_prefix='houseinfo:list'), name='list')
@method_decorator(decorator=cache_page(timeout=300, key_prefix='houseinfo:retrieve'), name='retrieve')
class HouseInfoViewSet(ModelViewSet):
...
- 添加筛选器,对关键字进行筛选,或者对价格进行排序,筛选价格区间等等
说明:筛选器就是对整个数据列表或者说是更准确的查询集进行数据筛选。对于想要的数据,我们可以通过添加filterset来进行数据过滤筛选。在这个筛选器中,我们可以自定义过滤器的筛选算法,以达到想要怎样的数据,就返还用户什么样的数据的效果。
# 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') # 排序内容