restful——规范 + APIview

一、 什么是RESTful

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
  • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
  • 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
  • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

10个规范:

-与后台做交互,通常使用https
-域名: -https://api.baidu.com(存在跨域问题) -https://www.baidu.com/api/

-版本 -https://www.baidu.com/api/v1 -https://www.baidu.com/api/v2
-路径,视网络上任何东西都是资源,均使用名词表示(可复数) -https://api.example.com/v1/books 不是:https://api.example.com/v1/delete_one_book
-method来表示增删查改 -https://api.example.com/v1/books get请求,获取所有书 -https://api.example.com/v1/books post请求,新增一本书 -https://api.example.com/v1/book/1 delete请求,删除一本书 -https://api.example.com/v1/book/1 delete请求,获取id为1的这本书 -https://api.example.com/v1/book/1 put/patch请求,修改id为1的这本书 -过滤,通过在url上传参的形式传递搜索条件 -https://api.example.com/v1/books?limit=10:只拿前10本 -https://api.example.com/v1/books?price=10:只拿价格为10的书
-状态码 -{status:100,}
-错误处理,应返回错误信息,error当做key { status:101, errors:'您没有权限操作这个事' }
-返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范 GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
-返回结果中提供链接(获取一本书) { id:1 name:lxx price:12 publish:www.xx.com/api/v1/publish/1 }

 

二、 基于Django实现

-在URL中:

url(r'^books/', views.Books.as_view()),
url(r'^book/(?P<id>\d+)', views.Book.as_view()),

-在views:

import json

def  user2(request):
    if request.method=='GET':
        dic = {'status':200,'name': 'lqz2', 'age': 18}
        return HttpResponse(json.dumps(dic))
    elif request.method=='POST':
        dic = {'status': 200, 'msg': '修改成功'}
        return JsonResponse(dic)

class Users(View):
    def get(self, request):
        dic = {'status':200,'name': 'lqz', 'age': 18}
        return HttpResponse(json.dumps(dic))

    def post(self, request):
        dic = {'status': 200, 'msg': '修改成功'}
        return JsonResponse(dic)

 

 三、APIVIew源码分析

Django执行流程请求来 中间件  >  URL 中匹配成功执行  as_view  >   dispatch 方法,重新封装了request  >   initialize_request  >   initial  >    认证组件  >   权限

组件   >   频率件   >    views中   >  中间件    >   响应

 

第一步:

第二步:

第三步:

第三步:

第四步:

ps:dispatch方法

# 传入的request是原生的request对象
# 接收的request已经不是原生的request了,但是它内部有个原生的request对象
request = self.initialize_request(request, *args, **kwargs)
self.initial(request, *args, **kwargs)#这里面有权限,认证,频率

 

四、restframework---Serializer

  干什么用的? 把python中的对象,转成json格式字符串--------序列化

models:

from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name
View Code

 

# 写一个类继承 serializers.Serializer
class BookSerializer(serializers.Serializer):
    id = serializers.CharField()
    # 通过source可以改名
    name = serializers.CharField(source='title')
    # 名称必须和表字段名相同
    price = serializers.CharField()

    xxx = serializers.CharField(source='test')
    # 1 变量名和source指定的值不能一样
    # 2 source='publish.name'还支持继续 .
    # 3 source 还支持方法(没用)
    # publish_name = serializers.CharField(source='publish.name')
    # publish_id = serializers.CharField(source='publish.pk')
    # 4 支持写方法,如下
        #方法一定传一个参数,是当前book对象
    publish_dic=serializers.SerializerMethodField()
    def get_publish_dic(self,obj):
        # 猜,这个obj应该是谁,当前book对象
        return {'id':obj.publish.pk,'name':obj.publish.name}
    authors=serializers.SerializerMethodField()
    # def get_authors(self,obj):
    #     # 所有作者queryset对象
    #     author_list=obj.authors.all()
    #     ll=[ {'name':author.name,'id':author.pk} for author in author_list]
    #     return ll
    def get_authors(self,obj):
        # 所有作者queryset对象
        author_list=obj.authors.all()
        author_ser=AuthorSer(instance=author_list,many=True)
        return author_ser.data

views:

from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name
View Code

注意:

source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))

如在模型中定义一个方法,直接可以在在source指定执行

choices:

class UserInfo(models.Model):
# 通过 XXX_choices =( ("1","普通用户"), )   1 为 真实数据,"普通用户"是为显示直观的名字
    user_type_choices = (
        (1,'普通用户'),
        (2,'VIP'),
        (3,'SVIP'),
    )
#通过choices 绑定关系
    user_type = models.IntegerField(choices=user_type_choices)

    username = models.CharField(max_length=32,unique=True)
    password = models.CharField(max_length=64)


#视图
ret=models.UserInfo.objects.filter(pk=1).first()
aa=ret.get_user_type_display()

#通过get_Foo_display方法获取user_type_choices中元组的第二元素值
 xx=serializers.CharField(source='get_user_type_display') #其中Foo为字段名

 

五、ModelSerializer

  跟表模型绑定的序列化

from app01 import models

# ModelSerializer跟表模型绑定的序列化
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        # 指定表模型
        model = models.Book
        # 序列化所有字段
        fields = '__all__'
        # 只想序列化title和id这俩字段
        # fields = ['title', 'id']
        # exclude 和fields 不要连用
        # exclude = ['title']
        # 深度,表示连表的深度
        # 不建议使用:下几层要取得参数不能控制,官方建议不要超过10,我给你的建议不要超过3
        # depth=1
        # 全取出来之后,可以在后面覆盖之前的值
        # 如果想让publish字段显示出版社的名字
        # publish = serializers.CharField(source='publish.name')
        # authors = serializers.SerializerMethodField()
        # def get_authors(self, obj):
        #     author_list = obj.authors.all()
        #     author_ser = AuthorSer(instance=author_list, many=True)
        #     return author_ser.data

    title = serializers.CharField(max_length=6, min_length=3, error_messages={'max_length': '太长了'})

    # 也有局部钩子和全局钩子
    def validate_title(self, value):
        from rest_framework import exceptions
        print(value)
        if value.startswith('sb'):
            raise exceptions.ValidationError('不能以sb开头')
        return value

六、Django restframewor之序列化

   -干什么用的? 把python中的对象,转成json格式字符串

-1 写一个类继承
class BookSerializer(serializers.Serializer):
    id = serializers.CharField()
    title = serializers.CharField()
    price = serializers.CharField()

-2 使用(视图类中)

# 写一个获取所有图书的接口
class Books(APIView):
    def get(self, request, *args, **kwargs):
        response = {'status': 100, 'msg': '成功'}
        book_list = models.Book.objects.all()
        # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True
        # 问?什么情况下many=False,instance=单个对象的时候
        book_ser = BookSerializer(book_list, many=True)  
        print(book_ser.data)   #序列化完成得到的字典
        response['books'] = book_ser.data
        return Response(response)

实例:

序列化类:

from app01 import models
from rest_framework import serializers


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        # 指定表模型
        model = models.Book
        # 序列化所有字段
        fields = '__all__'
View Code

表模型:

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.IntegerField()
    pub_date = models.DateField()
    publish = models.ForeignKey("Publish")
    authors = models.ManyToManyField("Author")

    def test(self):
        return self.title + str(self.price)

    def __str__(self):
        return self.title


class Publish(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()

    # def __str__(self):
    #     return self.name
    # return str(self.pk)


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
View Code

views代码:

# 写一个获取所有图书的接口
class Books(APIView):
    authentication_classes=[Auth,]
    def get(self, request, *args, **kwargs):

        response = {'status': 100, 'msg': '成功'}
        book_list = models.Book.objects.all()
        # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True
        # 问?什么情况下many=False,instance=单个对象的时候
        book_ser = BookSerializer(book_list, many=True)
        print(book_ser.data)
        response['books'] = book_ser.data
        return Response(response)

    #
    def post(self, request):
        response = {'status': 100, 'msg': '成功'}
        # 提交的字典
        # book = request.data
        # 传统方法,创建对象保存
        # 新方法,通过序列化组件保存,必须用继承自ModelSerializer
        # data注意是data
        print(request.data)
        book_ser = BookSerializer(data=request.data)
        # is_valid提交的字段校验通过
        if book_ser.is_valid():
            book_ser.save()
            response['book'] = book_ser.data
        else:
            response['msg'] = book_ser.errors
        # return Response(book_ser.data)
        return Response(response)

    #
    def put(self, request):

        # print(request.data)
        id = request.data.get("id")
        # print(id)
        response = {'status': 100, 'msg': '成功'}
        book = models.Book.objects.filter(pk=id).first()
        # 修改的话,要把book对象传过来
        book_ser = BookSerializer(data=request.data, instance=book)
        # is_valid提交的字段校验通过
        if book_ser.is_valid():
            # save既可以修改,又可以更新
            book_ser.save()
            response['book'] = book_ser.data
        else:
            response['msg'] = book_ser.errors
        # return Response(book_ser.data)
        return Response(response)

    #
    def delete(self,request):
        id = request.data.get("id")
        response = {'status': 100, 'msg': '删除成功'}
        book = models.Book.objects.filter(pk=id).delete()
        return Response(response)
View Code

 

在线格式化json:

  -https://www.json.cn/


posted @ 2019-02-20 20:49  萤huo虫  阅读(118)  评论(0编辑  收藏  举报