一.Django REST架构
注意使用这个的时候需要到app中注册:rest_framework
1.请求的过程:实体 ---> 数据 ---> 数据接口 ---> 网络API(HTTP/HTTPS)
2.Django REST框架是一个功能强大且灵活的工具包,用于构建Web API。
安装:
pip install django
pip install djangorestframework
3.用处:REST的用处 经常用在前后端分离的开发模式中,服务端提供API服务,前端用来展示数据,直接通过ajax来沟通。
二.反向生成models
1.从数据库反向迁移到models:
python manage.py inspectdb >comm
on/models.py
要把模型迁移到数据库:
managed = False 变成 true
三.基于类的视图函数
DRF框架中也是支持这两种的:
1.FBV-------基于函数的视图
2.CBV-------基于类的视图两者的区别在于:
(1).FBV更加的灵活
(2).CBV提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承) 可以用不同的函数针对不同的HTTP方法处理,不需要写多个if判断,提高代码可读性。
class EstateView(ListAPIView):
queryset = Estate.objects.all() #定义查询楼盘的数据
serializer_class=EstateSerializer(写一个序列化器)
#序列化器
class EstateSerializer(serializers.ModelSerializer):
class Meta:
model = Estate #序列化哪个类
exclude = ('district', 'agents') #不需要序列化
如果不需要序列化----那么查的时候也不需要查
Estate.objects.all().defer(需要不查询的字段)
以上步骤完成---在映射url:
path('estates/', EstateView.as_view())
把上面的EstateView类作为一个视图函数和'estates/'这个url对应。
c.拿单个-------继承RettrieveAPIView
class EstateView(RettrieveAPIView):
queryset = Estate.objects.all() #定义查询楼盘的数据
serializer_class=EstateSerializer(写一个序列化器)
以上和拿多个除了继承的类不同,没有其他的区别,有点区别是url的配置:
path('estates/<int:pk>/', EstateView.as_view()),
#其中int:后面的这个pk是默认的规范,必须叫pk.
d.单双一起拿-----python多重继承让类同时继承RettrieveAPIView,ListAPiView。
class EstateView(ListAPIView, RetrieveAPIView):
queryset = Estate.objects.all().defer('agents')
serializer_class=EstateSerializer
def get(self, request, *args, **kwargs):
if 'pk' in kwargs:
cls = RetrieveAPIView
else:
cls = ListAPIView
return cls.get(self, request, *args, **kwargs)
但以上的继承是两个父类都是有get方法的:先重写父类的get方法,然后我们做判断如果有pk这个参数,那么一定是拿单个的。就调用RettrieveAPIView这个父类。
e.新增-------在添加一个类继承CreateAPIView
但是注意:如果对同一个类的同一个字段你查看的时候不想查看它,但是新增加的时候确需要看见它,那么你需要写两个序列化器。有两个序列化器的时候你需要重写序列化器的类然后在做判断:
def get_serializer_class(self):
if self.request.method in ('POST', 'PUT', 'PATCH'):
return EstatePostSerializer
else:
return EstateSerializer
以上就根据请求的方法做出判断---不同的请求走不同的序列化器。
f.以上的方法过于的繁琐---有拿一个的删除和更新,和拿多个的新增
ListCreateAPIView(拿所有的新增),
RetrieveUpdateDestroyAPIView(拿一个的删除更新)
四.继承ModelViewSet做全套的接口
下面是对一个在view中房屋类型的类进行api接口的步骤:
1.写与模型相关的函数的类:
class HouseTypeViewSet(ModelViewSet):
queryset = HouseType.objects.all()
serializer_class = HouseTypeSerializer
2.在应用中注册URL:
配置路由全套房类查询的
需要对url进行注册
router = SimpleRouter()
router.register('housetypes', HouseTypeViewSet)
urlpatterns += router.urls
3.配置url路径:
urlpatterns += router.url
当然上面的也可以直接写入到urlpatterns的这个列表中,我们用的是列表的加法,也是一样的。
五.做缓存的不同方式
1.@cache_page-------这个是装饰器缓存只针对函数
通过设置cache_page可以设置不同地方的缓存,本地,mysql数据库,redis等。
CACHES = {
# 默认缓存
'default': {
# 用什么来做缓存
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
# 可以一主多从
'redis://118.31.5.162:6379/0', # 主机用来写
# 从机用来读(可以有多个)
],
# 区别命名
'KEY_PREFIX': 'django19062',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
# 池化技术(提前连接好,要用时借出去,用完还回来)用空间换时间
'CONNECTION_POOL_KWARGS': {
# 最大连接数
'max_connections': 512,
},
'PASSWORD': '361394621tmy',
}
},
# 会话缓存(会话放到缓存的好处: 性能好,不用手动清理,利于水平扩展)
'session': {
# 用什么来做缓存
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
# 可以一主多从
'redis://118.31.5.162:6379/1', # 主机用来写
# 'redis://49.233.152.190:6379/0', # 从机用来读(可以有多个)
],
# 区别命名
'KEY_PREFIX': 'django19062',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
# 池化技术(提前连接好,要用时借出去,用完还回来)用空间换时间
'CONNECTION_POOL_KWARGS': {
# 最大连接数
'max_connections': 1024,
},
'PASSWORD': '361394621tmy',
}
},
}
# 配置使用缓存来支持用户会话
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
# 会话数据放在哪一组缓存中
SESSION_CACHE_ALIAS = 'session'
# 设置会话保存的时长(单位秒)
SESSION_CACHE_AGE = 86400
2.@cache_response-----装饰可以用于类中的函数用于缓存。(第三方的库缓存---需要在setting中配置设置)
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.
3.在要做缓存的相应的类种加入CacheRseponseMixn的混入类,这个就是做缓存的相应的类。混入类----混入类会把父类里面的方法替换掉。实现父类本来没有的功能。注意:混入的类必须放在所有的类的前面才有效。但是用了游标分页是无法点击下一页的。用这个做缓存需要将分页设置为默认的分页。
4.把装饰函数的类打到类上面 ---就可以做缓存。
@method_decorator(decorator=cache_page(time=600),name="list")
这个就是把装饰器加到指定的list方法上。
@method_decorator(decorator=cache_page(timeout=600),name="list")
@method_decorator(decorator=cache_page(timeout=600),name="retrieve")
class HouseTypeViewSet(ModelViewSet):
queryset = HouseType.objects.all()
serializer_class = HouseTypeSerializer
pagination_class = None
注意:这种方法有一个缺点,就是你在其他的浏览器再开一次,他会重新加缓存,不会走已有的缓存的键。
六.分页
默认分页---setting里面配置:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 5,
}
不想分页就在相应的类中写:pagination_class=None
游标分页,自定义分页的类:
把分页的类写好----------放入需要分页的类函数中。
分页类:
class EstatePagination(CursorPagination):
page_size_query_param = 'size'
max_page_size = 20
ordering = 'estateid'
七.(补充的知识整理网络响应状态码)
八. 接口的筛选和排序
(精确筛选)
1.自写选择筛选器:
需要排序:
def get_queryset(self):
distid=self. request. GET. get(' district')
if distid:
self. queryset=self. queryset. filter(district=distid)
ordering=self. request. GET. get(' ordering')
if ordering:
self. queryset=self. queryset. order_by(ordering return self. queryset
2.使用三方库:django-filter
(1)pip install django-filter
(2).配置setting:apps中加入 "django_filters"
queryset = Estate.objects.all().defer("agents")
filter_backends = (DjangoFilterBackend,OrderingFilter)
# DjangoFilterBackend类支持数据筛选的类 OrderingFilter是支持排序的类。
filter_fields=("district",)
# filter_fields 根据什么是做精确的查询
ordering_fields=("hot","estateid")
#自定义排序的方式
ordering =("price")
#指定默认排序的方式
(模糊筛选)
1.查一个
(1)先自定义模糊的类:
class EstateFilterSet(django_filters.FilterSet):
intro=django_filters.CharFilter(lookup_expr="contains")
minhot=django_filters.NumberFilter(field_name="hot",lookup_expr="gte")
maxhot=django_filters.NumberFilter(field_name="hot",lookup_expr="lte")
(2)然后在查询的类中调用这个类:
filterset_class=EstateFilterSet
2.查多个是或者的关系:
在自定义查询类中写入以下的代码:
foo =django_filters.CharFilter(method="bar")
def bar(self,queryset,key,value):
queryset=queryset.filter(Q()| Q)
return queryset
# 要在几个不同的里面查询,用Q对象表示或者。
3.类的静态方法 查笔记
@staticmethod
def filter_by_keyword(queryset, key, value):
queryset = queryset.filter(Q(name__contains=value) |
Q(intro__s
tartswith=value))
return queryset
注意:
封装好的类查询都是很方便的,但是比起原生的sql语句性能都是很差的,原生的性能是最好的。
九.查询的限流
1.所有都限流
在setting中配置相关的文件。
在分页的设置中加入以下的代码:
REST_FRAMEWORK = {
# 按页码分页
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 5,
# 限流配置
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'anon': '5/min',
},
}
2.单个限流
在查询类中----写出限流的类
throttle_classes =() 或者再后面写自定义的限流的类