rest_framework(纯后端操作组件)中的各种插件方法

restful协议需要在这里码出来,不能仅仅是贴一个地址就作罢......

 restful规范的理解

其实就是一套编写接口的协议,协议规定如何编写以及如何设置返回值,状态码等信息

最显著的特点:restful给用户一个url,根据method的不同在后端做不同的处理,比如post是创建数据,get获取数据,put和patch修改数据,delete是删除数据等
如果没有restful的话我们这些method请求不同,要分别设置与之对应的url,比如add_class/delete_class/post_class/get_class/
这里还有其他的比如版本,我们的程序有的时候会有版本迭代,会出现两个版本共存的情况,就需要加以区分,版本可以放到url,请求头(accept/自定义)

未完待续...

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

restful  这里具体解释了我们的面相资源编程的特点

我们的django里面都是前端和后端绑定在一起操作的,针对数据库进行增删改查操作,然后把数据渲染到页面上,交给浏览器显示给用户,供用户操作,

在vue里面我们的一切前端页面操作都是独立的,跟我们的django分开了,脱离后端,纯粹的前端,实现解耦.

在rest_framework里面,我们的一切操作都是纯粹的后端,不跟前端有任何瓜葛,实现解耦.

 

我们的django里面前端和后端要耦合一个关键的点是,我们的django生命请求周期里面,url跟view视图还有HTML模板是一整套流程,彼此胶合在一起,不可拆分,我们的url里面正则匹配上之后就会执行后面对应的view视图,然后在视图里面处理逻辑代码之后,就会把数据传给HTML模板,然后交给浏览器进行渲染,显示给我们的用户.

但是我们在rest_framework里面就不是这样的,它是一个组件,专门服务于后端使用,它主要的核心就是面相资源编程,这里我们引入了一个新的概念,面相资源编程,之前接触的都是面相对象编程和面相过程编程,

这个面相资源就是指我们所面对的一切数据都视作资源,它的核心的点就是把我们的url请求给拆分了,我们在django里面都是习惯了把一个url发送出去之后,在我们的HTML模板里面的标签来区分是post请求还是get请求,然后再由我们的视图来根据不同的请求处理数据,但是在我们的面向资源变成里面则不是这样的,一个url,我们在rest_framework里面把它拆分成更多的分支,如下即是

这是从源码里面摘出来的:

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

这一段是我们从源码里面摘出来的,所有的请求都是在这个列表里面,当然了,我们主要用的就是get/post居多,再就是delete,

我们的每一条url都指定到具体的请求类型从上面的列表里面选取仅限于列表里面的类型,然后在访问url的时候,我们除了输入ur就可以
直接取出数据,post请求就直接提交数据,然后再具体的请求下面进行具体操作.
这样我们就不需要使用HTML前端模板来决定这条url是什么请求了,就可以从根源上跟我们的前端彻底脱离,实现功能解耦.
这里需要一个协助的工具,postman,它就是充当我们的浏览器自带渲染页面,让我们在开发阶段使用起来更加直观能看到效果,
我们要用的话需要在电脑上下载,

 

url的请求方式被拆分之后,紧接着我们就可以在里面给它加上参数了,比如我们的数据分页,比如我们的filter过滤等等,一样是使用&分割多个条件,也需要?进行区分,

基本上整个流程就是这样的,所以我们使用rest_framework的时候就不会写前端页面,那我们要跟前端实现数据交互的话,就需要通过一个json字符串来发送数据,我们把view视图里面的逻辑代码完成之后,返回值一律改成Response字符串,前端部分会有VUE通过ajax来接收后端的json字符串.

这里需要补充的点是我们的rest_framework的前身是CBV===>class basic view 基于类的视图

所以我们的url后面不是FBV(function basic view)而是一个类,基于类的视图,所以我们要了解rest_framework就需要对CBV有一定了解

点进去看   摘自yuanxiansheng博客

效果图附上,会更加直观:

这里就是postman的界面:

 

这里的流程我们再梳理一遍,其实我们的rest_framework的流程都是基于RESTful规范来的,

 

restful是什么呢?

官方说法是:REST代表的是一种软件架构风格,是Representational State Transfer的简称,中文翻译为"表征状态转移",

 这里需要把restful的流程给补充完整......未完待续

rest_framework下载步骤:

使用cmd命令行============>>pip install rest_framework

下载之后,就可以使用编辑器启动项目了,

 

 

 

 

代码如下:

  1 """
  2 Django settings for rest_test project.
  3 
  4 Generated by 'django-admin startproject' using Django 1.11.9.
  5 
  6 For more information on this file, see
  7 https://docs.djangoproject.com/en/1.11/topics/settings/
  8 
  9 For the full list of settings and their values, see
 10 https://docs.djangoproject.com/en/1.11/ref/settings/
 11 """
 12 
 13 import os
 14 
 15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 17 
 18 # Quick-start development settings - unsuitable for production
 19 # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
 20 
 21 # SECURITY WARNING: keep the secret key used in production secret!
 22 SECRET_KEY = 'pxf)9)k2j1@62yq4a!7s(in5i*p9c#18zb-mh6h-)oxg7u4-o^'
 23 
 24 # SECURITY WARNING: don't run with debug turned on in production!
 25 DEBUG = True
 26 
 27 ALLOWED_HOSTS = []
 28 
 29 # Application definition
 30 
 31 INSTALLED_APPS = [
 32     'django.contrib.admin',
 33     'django.contrib.auth',
 34     'django.contrib.contenttypes',
 35     'django.contrib.sessions',
 36     'django.contrib.messages',
 37     'django.contrib.staticfiles',
 38     'demo.apps.DemoConfig',
 39     'rest_framework',
 40     'api.apps.ApiConfig',
 41     'tiny.apps.TinyConfig',
 42 ]
 43 
 44 MIDDLEWARE = [
 45     'django.middleware.security.SecurityMiddleware',
 46     'django.contrib.sessions.middleware.SessionMiddleware',
 47     'django.middleware.common.CommonMiddleware',
 48     'django.middleware.csrf.CsrfViewMiddleware',
 49     'django.contrib.auth.middleware.AuthenticationMiddleware',
 50     'django.contrib.messages.middleware.MessageMiddleware',
 51     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 52 ]
 53 
 54 ROOT_URLCONF = 'rest_test.urls'
 55 
 56 TEMPLATES = [
 57     {
 58         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 59         'DIRS': [os.path.join(BASE_DIR, 'templates')]
 60         ,
 61         'APP_DIRS': True,
 62         'OPTIONS': {
 63             'context_processors': [
 64                 'django.template.context_processors.debug',
 65                 'django.template.context_processors.request',
 66                 'django.contrib.auth.context_processors.auth',
 67                 'django.contrib.messages.context_processors.messages',
 68             ],
 69         },
 70     },
 71 ]
 72 
 73 WSGI_APPLICATION = 'rest_test.wsgi.application'
 74 
 75 # Database
 76 # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
 77 
 78 DATABASES = {
 79     'default': {
 80         'ENGINE': 'django.db.backends.sqlite3',
 81         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 82     }
 83 }
 84 
 85 # Password validation
 86 # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
 87 
 88 AUTH_PASSWORD_VALIDATORS = [
 89     {
 90         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
 91     },
 92     {
 93         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
 94     },
 95     {
 96         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
 97     },
 98     {
 99         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100     },
101 ]
102 
103 # Internationalization
104 # https://docs.djangoproject.com/en/1.11/topics/i18n/
105 
106 LANGUAGE_CODE = 'en-us'
107 
108 TIME_ZONE = 'UTC'
109 
110 USE_I18N = True
111 
112 USE_L10N = True
113 
114 USE_TZ = True
115 
116 # Static files (CSS, JavaScript, Images)
117 # https://docs.djangoproject.com/en/1.11/howto/static-files/
118 
119 STATIC_URL = '/static/'
120 
121 # 这里是全局配置,我们按照源码里面的流程写的,我们自己有自己定义的参数就按照我们自己的参数走,否则,就走源码里面默认的参数,
122 REST_FRAMEWORK = {
123     "DEFAULT_AUTHENTICATION_CLASSES": ["api.service.auth.MyAuthentication"],  # 登录验证
124     "DEFAULT_PERMISSION_CLASSES": ["api.service.permission.VIPPermission"],  # 权限验证
125     "DEFAULT_THROTTLE_CLASSES": ["api.service.throttling.MyThrottle"],  # 频率验证
126     # "DEFAULT_THROTTLE_RATES": {"xxx": "4/m"},
127     "PAGE_SIZE": 2
128 }
settings

 

 1 """rest_test URL Configuration
 2 
 3 The `urlpatterns` list routes URLs to views. For more information please see:
 4     https://docs.djangoproject.com/en/1.11/topics/http/urls/
 5 Examples:
 6 Function views
 7     1. Add an import:  from my_app import views
 8     2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
 9 Class-based views
10     1. Add an import:  from other_app.views import Home
11     2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
12 Including another URLconf
13     1. Import the include() function: from django.conf.urls import url, include
14     2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
15 """
16 from django.contrib import admin
17 from django.conf.urls import url, include
18 from rest_framework import routers
19 from demo import views
20 from api import views as apiviews
21 from tiny import views as tinyviews
22 
23 router = routers.DefaultRouter()  # 这里是类实例化出来的对象,router就是我们的对象,它去调用类里面的url方法,自动生成url路由
24 router.register(r'users', views.UserViewSet)
25 router.register(r'groups', views.GroupViewSet)
26 router.register(r'publish', views.PublishViewSet)
27 
28 router.register(r'books', apiviews.BookViewSet)
29 # Wire up our API using automatic URL routing.
30 # Additionally, we include login URLs for the browsable API.
31 urlpatterns = [
32     # 这里是quickstart里面用到的两个url
33     # url(r'^', include(router.urls)),
34     # url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
35     # ============================================================================================
36 
37 
38     # url(r'^publishes/$', apiviews.PublishView.as_view(), name='publish_list'),
39     # url(r'^publishes/(?P<pk>\d+)/$', apiviews.PublishDetailView.as_view(), name='publish_detail'),
40     #
41     # url(r'^books/$', apiviews.BookView.as_view(), name='book_list'),
42     # url(r'^books/(?P<pk>\d+)/$', apiviews.BookDetailView.as_view(), name='book_detail'),
43 
44     url(r'', include(router.urls)),  # 它会自动给我们生成4个url,
45     # 我们这里boks开头的两个url是在我们上面的books基础上进行升级的,我们让两个url都走同一个视图,
46     # 然后在这个视图的基础上进行数据的分发,使用键值对的方式进行分发,这样我们的每一个请求过来都可以走到指定的函数方法里面
47     # url(r'^boks/$', apiviews.BookViewSet.as_view({'get': 'list', 'post': 'create'}), name='book_list'),
48     # url(r'^boks/(?P<pk>\d+)/$', apiviews.BookViewSet.as_view({'get': 'retrieve', 'delete': 'destroy', 'put': 'update'}),
49     #     name='book_detail'),
50     #
51     url(r'^pub/$', apiviews.PublishViewSet.as_view({'get': 'list', 'post': 'create'}), name='publish_list'),
52     url(r'^pub/(?P<pk>\d+)', apiviews.PublishViewSet.as_view({'get': 'retrieve', 'delete': 'destroy', 'put': 'update'}), name='publish_detail'),
53 
54 
55     url(r'^admin', admin.site.urls),
56     url(r'^foo/$', tinyviews.foo),
57     url(r'^index/$', tinyviews.Index.as_view()),
58 
59     url(r'^login/$', apiviews.LoginView.as_view()),
60 
61 ]
url

 

 1 from django.db import models
 2 
 3 
 4 # Create your models here.
 5 class Book(models.Model):
 6     title = models.CharField(max_length=32)
 7     price = models.IntegerField()
 8     pub_date = models.DateField()
 9     publish = models.ForeignKey('Publish')
10     authors = models.ManyToManyField('Author')
11 
12     def __str__(self):
13         return self.title
14 
15 
16 class Publish(models.Model):
17     name = models.CharField(max_length=32)
18     email = models.EmailField()
19 
20     def __str__(self):
21         return self.name
22 
23 
24 class Author(models.Model):
25     name = models.CharField(max_length=32)
26     age = models.IntegerField()
27 
28     def __str__(self):
29         return self.name
30 
31 
32 class User(models.Model):
33     user = models.CharField(max_length=32)
34     pwd = models.CharField(max_length=32)
35     user_type = models.IntegerField(choices=((1, 'normal_customer'), (2, 'higher_customer'), (3, 'top_level_customer')),
36                                     default=1)
37 
38 
39 class UserToken(models.Model):
40     user = models.OneToOneField(to='User')
41     token = models.CharField(max_length=128)
model

 

  1 from django.shortcuts import render
  2 
  3 # Create your views here.
  4 from rest_framework.views import APIView
  5 import json
  6 from .models import *
  7 from rest_framework.response import Response
  8 from rest_framework import mixins
  9 from rest_framework import generics
 10 from api.service.serializers import *
 11 from api.service.permission import VIPPermission
 12 from api.service.auth import MyAuthentication
 13 from api.service.throttling import MyThrottle
 14 from api.service.pagination import MyPageNumber
 15 # 这里是相应器
 16 from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer
 17 
 18 # 这里是解析器,rest_framework里面有4种解析器,
 19 from rest_framework.parsers import JSONParser, FormParser, FileUploadParser, MultiPartParser
 20 
 21 # class BookView(APIView):
 22 #     """
 23 #     我们的CBV里面的方法不是可以随便写的,是有指定范围的,
 24 #     http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
 25 #     以上这个列表是源码里面摘出来的,该列表里面的方法都可以在CBV里面使用,只有这个列表里面的方法才可以.
 26 #     """
 27 #
 28 # def get(self, request, *args, **kwargs):
 29 #     book_list = Book.objects.all()
 30 #         # 方式一
 31 #         # book_list=list(Book.objects.all().values('title','price'))
 32 #         # 方式二
 33 #         # temp=[]
 34 #         # for book in book_list:
 35 #         #     temp.append({
 36 #         #         'title':book.pk,
 37 #         #         'price':book.price,
 38 #         #         'pub_date':book.pub_date,
 39 #         #     })
 40 #         # 方式三
 41 #         # from django.core import serializers
 42 #         # temp=serializers.serialize('json',book_list)
 43 #         # return HttpResponse(temp)
 44 #         # 方式四
 45 #         # 将book_list转换成json数据[{},{},{}]
 46 # bs = BookSerializers(book_list, many=True, context={'request': request})
 47 #         # many默认是false,我们把queryset数据集合直接放到这里就可以把数据转换成json数据,
 48 #         # BookSerializers有两个参数,第一个是数据,第二个是many值,many默认是false,第一个参数的数据默认是一个单独的数据对象,
 49 #         # 第一个参数也可以是是数据集合,如果是集合的话就是多个值,many值需要改为True,
 50 #         # print(bs.data)  # 序列化的结果
 51 #         """
 52 #         [
 53 #         OrderedDict(
 54 #         [('id', 1),
 55 #          ('authors',
 56 #          [{'pk': 1, 'name': 'Eval'}]
 57 #          ),
 58 #           ('title', 'python'),
 59 #            ('price', 23),
 60 #             ('pub_date', '2018-02-07'),
 61 #             ('publish', 1)]),
 62 #              OrderedDict(
 63 #              [('id', 2),
 64 #               ('authors',
 65 #               [
 66 #               {'pk': 1, 'name': 'Eval'}
 67 #               ]),
 68 #               ('title', 'java开发实战'),
 69 #                ('price', 39),
 70 #                 ('pub_date', '2017-11-22'),
 71 #                 ('publish', 2)]),
 72 #                 OrderedDict([
 73 #                 ('id', 3),
 74 #                  ('authors',
 75 #                  [
 76 #                  {'pk': 2, 'name': 'aliven'},
 77 #                   {'pk': 1, 'name': 'Eval'}
 78 #                   ]),
 79 #                   ('title', '百年孤独'),
 80 #                   ('price', 79),
 81 #                    ('pub_date', '2018-01-10'),
 82 #                     ('publish', 2)]),
 83 #                      OrderedDict([('id', 4),
 84 #                      ('authors', [
 85 #                      {'pk': 2, 'name': 'aliven'}, {'pk': 3, 'name': 'egon'}
 86 #                      ]),
 87 #                      ('title', 'sound of music'),
 88 #                      ('price', 35),
 89 #                       ('pub_date', '2017-05-24'),
 90 #                       ('publish', 1)
 91 #                       ])
 92 #                       ]
 93 #         """
 94 #
 95 # return Response(bs.data)
 96 
 97 # #
 98 # def post(self, request, *args, **kwargs):
 99 #     bs = BookSerializers(data=request.data, context={'request': request})
100 #     if bs.is_valid():
101 #         bs.save()
102 #         return Response(bs.data)
103 #     else:
104 #         return Response(bs.errors)
105 
106 
107 #
108 #
109 # """
110 # class BookSerializers(serializers.Serializer):
111 #     title=serializers.CharField(max_length=32)
112 #     price=serializers.IntegerField()
113 #     pub_date=serializers.DateField()
114 #     publish=serializers.CharField(source='publish.pk')
115 #     authors=serializers.CharField()
116 # temp=[]
117 # for book in book_list:
118 #     temp.append({
119 #         'title':book.title,
120 #         'price':book.price,
121 #         'pub_date':book.publish.pk,
122 #         'authors':book.authors,
123 #     })
124 #
125 #     [
126 #     {
127 #     'title':'python',
128 #     'price':45,
129 #     'publish':'1'
130 #     },
131 #     {
132 #     'title':'go',
133 #     'price':89,
134 #     'publish':'2'
135 #     }
136 #     ]
137 # """
138 #
139 
140 # class BookDetailView(APIView):
141 #     def get(self, request, id, *args, **kwargs):
142 #         obj = Book.objects.filter(pk=id).first()
143 #         if obj:
144 #             res = BookSerializers(obj, context={'request': request})
145 #             return Response(res.data)
146 #         else:
147 #             return Response()
148 #
149 #     def delete(self, request, id, *args, **kwargs):
150 #         Book.objects.filter(pk=id).delete()
151 #         return Response()
152 #
153 #     def put(self, request, id, *args, **kwargs):
154 #         obj = Book.objects.filter(pk=id).first()
155 #         res = BookSerializers(data=request.data, instance=obj, context={'request': request})
156 #         if res.is_valid():
157 #             return Response(res.data)
158 #         else:
159 #             return Response(res.errors)
160 
161 
162 # =====================mixin===================
163 """
164 # 这里是我们的mixins方法构建的视图
165 
166 class BookView(mixins.ListModelMixin,
167                mixins.CreateModelMixin,
168                generics.GenericAPIView):
169     queryset = Book.objects.all()
170     serializer_class = BookSerializers
171 
172     def get(self, request, *args, **kwargs):
173         return self.list(request, *args, **kwargs)
174 
175     def post(self, request, *args, **kwargs):
176         return self.create(request, *args, **kwargs)
177 
178 
179 class BookDetailView(
180     mixins.RetrieveModelMixin,
181     mixins.DestroyModelMixin,
182     mixins.UpdateModelMixin,
183     generics.GenericAPIView
184 ):
185     queryset = Book.objects.all()
186     serializer_class = BookSerializers
187 
188     def get(self, request, *args, **kwargs):
189         return self.retrieve(request, *args, **kwargs)
190 
191     def delete(self, request, *args, **kwargs):
192         return self.destroy(request, *args, **kwargs)
193 
194     def put(self, request, *args, **kwargs):
195         return self.update(request, *args, **kwargs)
196 
197 
198 class PublishView(mixins.ListModelMixin,
199                   mixins.CreateModelMixin,
200                   generics.GenericAPIView):
201     queryset = Publish.objects.all()
202     serializer_class = PublishSerializers
203 
204     def get(self, request, *args, **kwargs):
205         return self.list(request, *args, **kwargs)
206 
207     def post(self, request, *args, **kwargs):
208         return self.create(request, *args, **kwargs)
209 
210 
211 class PublishDetailView(
212     mixins.RetrieveModelMixin,
213     mixins.DestroyModelMixin,
214     mixins.UpdateModelMixin,
215     generics.GenericAPIView
216 ):
217     queryset = Publish.objects.all()
218     serializer_class = PublishSerializers
219 
220     def get(self, request, *args, **kwargs):
221         return self.retrieve(request, *args, **kwargs)
222 
223     def delete(self, request, *args, **kwargs):
224         return self.destroy(request, *args, **kwargs)
225 
226     def put(self, request, *args, **kwargs):
227         return self.update(request, *args, **kwargs)
228 """
229 
230 
231 class BookView(generics.ListCreateAPIView):
232     queryset = Book.objects.all()
233     serializer_class = BookSerializers
234 
235 
236 class BookDetailView(generics.RetrieveUpdateDestroyAPIView):
237     queryset = Book.objects.all()
238     # print(1, args, 2, kwargs)
239     # 1()2{'pk': '5'}
240     serializer_class = BookSerializers
241 
242 
243 class PublishView(generics.ListCreateAPIView):
244     queryset = Publish.objects.all()
245     serializer_class = PublishSerializers
246 
247 
248 class PublishDetailView(generics.RetrieveUpdateDestroyAPIView):
249     queryset = Publish.objects.all()
250     serializer_class = PublishSerializers
251 
252 
253 # 这里就真的是终极版了.....有与之匹配的url
254 from rest_framework.viewsets import ModelViewSet
255 
256 
257 # 我们加在类里面的都是局部验证,全局验证都是在我们的setting.py配置文件里面的
258 class BookViewSet(ModelViewSet):
259     # authentication_classes = [MyAuthentication]  # 登录验证
260     # permission_classes = [VIPPermission]  # 权限验证
261     # throttle_classes = [MyThrottle, ]  # 这里是频率验证
262     # pagination_class = MyPageNumber  # 这里因为是分页我们只有一个,所以就不需要列表了,否则会报错
263     queryset = Book.objects.all()
264     serializer_class = BookSerializers
265     parser_classes = [JSONParser, FormParser, MultiPartParser]  # 解析器验证
266     # renderer_classes = [BrowsableAPIRenderer, JSONRenderer]  # 相应器验证
267 
268 
269 class PublishViewSet(ModelViewSet):
270     # authentication_classes = [MyAuthentication]
271     # permission_classes = [VIPPermission]
272     queryset = Publish.objects.all()
273     serializer_class = PublishSerializers
274     parser_classes = [FormParser]
275 
276 
277 from .models import *
278 from django.http import JsonResponse
279 
280 
281 # 这里是获取随机生成的字符串,随着时间的不同,它会随时变换,把时间和md5都加进去
282 def get_random_str(user):
283     import hashlib, time
284     ctime = str(time.time())
285 
286     md = hashlib.md5(bytes(user, encoding='utf8'))
287     md.update(bytes(ctime, encoding='utf8'))
288 
289     return md.hexdigest()
290 
291 
292 # 登录,用于验证的CBV
293 class LoginView(APIView):
294     def post(self, request, *args, **kwargs):
295         user = request.data.get("user")
296         pwd = request.data.get('pwd')
297         user = User.objects.filter(user=user, pwd=pwd).first()
298         res = {"state_code": 200, "msg": None}
299         if user:
300             random_str = get_random_str(user.user)
301             user_token_obj = UserToken.objects.update_or_create(user=user, defaults={'token': random_str})
302             res['msg'] = 'success'
303             res['token'] = random_str
304         else:
305             res['msg'] = 'user or pwd is wrong!'
306             res['state_code'] = 10086
307         return JsonResponse(res)
View视图

 在view视图中我们都可以继承哪些类:

如图所示:

接下来就是我们的配置文件在django项目里面主逻辑的App里面建立一个文件夹,里面放上我们的配置文件:

 1 from rest_framework import exceptions
 2 from ..models import *
 3 from rest_framework.authentication import BaseAuthentication
 4 
 5 
 6 class MyAuthentication(BaseAuthentication):
 7     def authenticate(self, request):
 8         token = request._request.GET.get('token')
 9         user_token_obj = UserToken.objects.filter(token=token).first()
10         if user_token_obj:
11             return user_token_obj.user, token
12         else:
13             raise exceptions.AuthenticationFailed('sorry no permission!')
auth

 

 1 from rest_framework.permissions import BasePermission
 2 
 3 
 4 class VIPPermission(BasePermission):
 5     message = 'you have not got permission!'
 6 
 7     def has_permission(self, request, view):
 8         if request.user.user_type == 3:
 9             return True
10         else:
11             return False
permission

 

  1 from rest_framework import serializers  # 序列化器,主要作用是把数据序列化
  2 from ..models import *
  3 
  4 
  5 class BookSerializers(serializers.ModelSerializer):
  6     # 这里是把我们的外键关联字段变成a标签,有超链接,可以点击就跳转到相应的页面
  7     # publish = serializers.HyperlinkedIdentityField(
  8     #     view_name='publish_detail',  # 这里的view_name就是反向解析的名字,也就是我们写到url里面的那个名字
  9     #     lookup_field='publish_id',  # 这里是我们所要设置成a标签超链接的字段名字
 10     #     lookup_url_kwarg='pk'  # 这里是关键字我们在url里面加上的关键字参数,它跟我们反向解析的url里面的有名分组一样的名字,要对应上,
 11     #     我们的超链接a标签里面的这些参数都是根据我们的url来进行反向解析的,第一个参数name就是反向解析的名字
 12         # 第三个参数url_kwarg是我们的url里面的正则匹配的有名分组,
 13         # 第二个参数是我们的这个正则匹配有名分组所对应的值,我们是根据id值去匹配的,那么我们直接从对象里面把id取出来即可,
 14     # url(r'^publishes/(?P<pk>\d+)/$', apiviews.PublishDetailView.as_view(), name='publish_detail'),
 15         #     publishes/(?<pk>\d+)/$
 16     # )
 17 
 18     class Meta:
 19         model = Book
 20         fields = "__all__"
 21         # 这里有两种写法,上面使用__all__得到的数据效果是这样的
 22         """
 23         [
 24           {
 25             "id": 1,
 26             "authors": [
 27               {
 28                 "pk": 1,
 29                 "name": "Eval"
 30               }
 31             ],
 32             "title": "python",
 33             "price": 23,
 34             "pub_date": "2018-02-07",
 35             "publish": 1
 36           },
 37           {
 38             "id": 2,
 39             "authors": [
 40               {
 41                 "pk": 1,
 42                 "name": "Eval"
 43               }
 44             ],
 45             "title": "java开发实战",
 46             "price": 39,
 47             "pub_date": "2017-11-22",
 48             "publish": 2
 49           },
 50           {
 51             "id": 3,
 52             "authors": [
 53               {
 54                 "pk": 2,
 55                 "name": "aliven"
 56               },
 57               {
 58                 "pk": 1,
 59                 "name": "Eval"
 60               }
 61             ],
 62             "title": "百年孤独",
 63             "price": 79,
 64             "pub_date": "2018-01-10",
 65             "publish": 2
 66           },
 67           {
 68             "id": 4,
 69             "authors": [
 70               {
 71                 "pk": 2,
 72                 "name": "aliven"
 73               },
 74               {
 75                 "pk": 3,
 76                 "name": "egon"
 77               }
 78             ],
 79             "title": "sound of music",
 80             "price": 35,
 81             "pub_date": "2017-05-24",
 82             "publish": 1
 83           }
 84         ]
 85         """
 86         # 我们的exclude方法里面,不需要authors,以及下面的get_authors函数方法
 87         # exclude = ['authors', ]
 88         """
 89         这里是使用exclude方法取到的数据
 90           {
 91             "id": 1,
 92             "title": "python",
 93             "price": 23,
 94             "pub_date": "2018-02-07",
 95             "publish": 1
 96           },
 97           {
 98             "id": 2,
 99             "title": "java开发实战",
100             "price": 39,
101             "pub_date": "2017-11-22",
102             "publish": 2
103           },
104           {
105             "id": 3,
106             "title": "百年孤独",
107             "price": 79,
108             "pub_date": "2018-01-10",
109             "publish": 2
110           },
111           {
112             "id": 4,
113             "title": "sound of music",
114             "price": 35,
115             "pub_date": "2017-05-24",
116             "publish": 1
117           }
118         ]
119         """
120 
121     authors = serializers.SerializerMethodField()
122 
123     def get_authors(self, obj):
124         # print('obj>>>>>',obj)
125         """
126         obj是我们这个表里的所有数据的__str__反射的字段名
127         obj>>>>> python
128         obj>>>>> java开发实战
129         obj>>>>> 百年孤独
130         obj>>>>> sound of music
131         """
132         temp = []
133         for author in obj.authors.all():
134             temp.append({'pk': author.pk, 'name': author.name})
135         return temp
136 
137 
138 class PublishSerializers(serializers.ModelSerializer):
139     class Meta:
140         model = Publish
141         fields = "__all__"
serializers

 

 1 from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination,CursorPagination
 2 
 3 
 4 # 这里我们自定义一个类然后继承我们的父类PageNumberPagination,然后把它里面的属性拿出来我们在这里重新定义,就可以得到我们自定义的效果,
 5 # 就相当于是使用它的方法,然后按照我们自定义的参数来实现我们的效果
 6 class MyPageNumber(PageNumberPagination):
 7     page_size = 1
 8     page_query_param = 'per_page'
 9     page_size_query_description = 'length'
10     max_page_size = 2
page

 

 1 from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
 2 from rest_framework.exceptions import APIException
 3 import time
 4 
 5 
 6 # 这里是我们自己写的,throttle
 7 vist_dic = {}
 8 
 9 
10 class MyThrottle(BaseThrottle):
11     def __init__(self):
12         self.history = None
13 
14         """
15         我们要设置访问频率,就需要先把数据类型整理出来,要设置在一分钟之内对该url的访问不得超过3次的话,
16         需要考虑到用户是否已经登录的状态,每一个用户唯一的标识就是ip地址,以键值对的格式,ip为键,访问时间为值,
17         以列表的形式存起来,然后把不符合条件的时间删除,把符合条件的时间给添加到该列表里面,保证列表里面只有3个值
18         """
19 
20     #  我们从throttle里面的源码看到这个allow_request最终的返回值是bool值,所以我们照着写同样要把返回值写成bool值
21     def allow_request(self, request, view):
22         # 获取到用户的ip地址
23         # remote_addr=self.get_ident(request)  # 这里是调用我们的父类BaseThrottle里面的方法
24         remote_addr = request.META.get('REMOTE_ADDR')
25         xff = request.META.get('HTTP_X_FORWARDED_FOR')
26         print("xff",xff,type(xff))  # xff None <class 'NoneType'>
27         ctime = time.time()  # 获取当前时间
28 
29         # 当第一次访问来临时我们就直接把时间放到列表里面去
30         if remote_addr not in vist_dic:  # 判断该ip地址是否在我们的这个字典里面
31             vist_dic[remote_addr] = [ctime]  # 然后把访问时间放到字典里面作为值
32             return True
33         self.history = vist_dic[remote_addr]
34         # print(self.history)  # 这里的history就是存储我们的每一次访问的有效时间,就是从我们的vist_dic里面把存储的
35         # 有效时间拿出来放到这里来了,
36         """
37         [1523431104.138973, 1523431101.737836, 1523431096.8755577]
38         这里打印出来的就是我们的有效访问时间,
39         """
40 
41         # 当第2,3次访问来临时,我们就需要判断请求的间隔时间了
42         if len(vist_dic[remote_addr]) < 3:  # 判断列表的长度
43             vist_dic[remote_addr].insert(0, ctime)  # 把最新的访问时间永远插入到列表里面的索引为0的地方
44             # print(vist_dic)
45             """
46             {'127.0.0.1': [
47             1523431321.6974168,
48             1523431320.898371,
49             1523431320.044322
50             ]}
51             """
52 
53             return True
54 
55         if ctime - vist_dic[remote_addr][-1] > 60:
56             """
57             这里是根据我们的限制条件,每一分钟里面同一个ip地址可以访问3次,来进行判断,
58             把不符合条件的访问时间给删除,然后把符合条件的访问时间给添加到列表里面去
59             """
60             vist_dic[remote_addr].insert(0, ctime)
61             vist_dic[remote_addr].pop()
62 
63         return False
64 
65     def wait(self):
66         # 源码里面有这个wait方法,
67         """
68         显示给用户还需要多长时间才可以访问,
69         :return:"detail": "Request was throttled. Expected available in 35 seconds."
70         """
71         ctime = time.time()
72         return 60 - (ctime - self.history[-1])
73 
74 
75 # 这里是更加简单的写法直接继承父类,然后调用即可
76 # class MyThrottle(SimpleRateThrottle):
77 #     scope = 'xxx'
78 #
79 #     def get_cache_key(self, request, view):
80 #         return self.get_ident(request)
throttle

 

 

流程图:

=======================================================================================================================================

 

posted @ 2018-04-11 21:39  dream-子皿  阅读(642)  评论(0)    收藏  举报