RESTful规范

Posted di2wu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RESTful规范相关的知识,希望对你有一定的参考价值。

一、学习restframework之前准备

1、json格式若想展示中文,需要ensure_ascii=False

import json

dic={name:你好}
print(json.dumps(dic,ensure_ascii=False))

2、不基于restframework也可以通过django来做符合restframework的规范接口设计,Jsonresponse,若想在json展示中文,如下

def books(request):

    ll=[{name:python全站开发,price:20},{name:linux,price:30}]

    # return HttpResponse(json.dumps(ll))
    return JsonResponse(ll,safe=False,json_dumps_params={ensure_ascii:False})

3、原声cbv执行流程

url(r‘^books/$‘, views.Book.as_view()),


原声cbv执行流程---》as_view----》dispatch---》相应到具体的函数 from django.views import View class Book(View): def get(self,reuquest): # reuquest.method return HttpResponse(get) def post(self,request): return HttpResponse(post)

3、分析restframework

一 restfu(规范)
    是什么:
        -面向资源编程
        -getBooklist:获取图书列表
        -符合规范的:books
    规范:
        -method:get----》books----》取到所有的书
                
                 post———》books---》新增图书
                 
                 put/patch--》books/id---》修改图书
                 
                 delete---》books/id---》删除图书
        -https://api.example.com/v1/zoos?limit=10
        -

二 drf
    安装(app):pip3 install djangorestframework
    -基于drf写resful的接口,得写CBV
    -request对象,源码分析
    -APIView源码分析   

二、restframework使用

1、POST没法解析json格式,可以在body里取值出来序列化反序列化操作转成字典,目前drf可以在前台提交post后台取值的话用data,

from rest_framework.views import APIView

class Book(APIView):
    def get(self,request):
        # 拿原来的request对象
        # request._request
        # print(request.method)
        # print(request._request.method)
        # request.POST
        # request.method
        return HttpResponse(get)
    def post(self,request):
        print(request.method)
        print(request._request.method)
        print(request.POST)

        # 用apiview之后,再取数据,从request.data
        print(request.data)
        return HttpResponse(post)

2、用Postman模拟发http请求,网上直接下载,data可以类似于解析器,解析form-data,urlencoded,json格式,而django只能解析form-data,urlencoded两种格式

三、序列化组件

1、从数据库取出来的都是qs类型,里面套了一个一个对象,要传到前台去必须要json格式,符合drf规范的第一种方式

数据库配置
DATABASES = { default: { ENGINE: django.db.backends.mysql, NAME: resful, USER:root, PASSWORD:‘‘, HOST:127.0.0.1, PORT:3306, } }

models取值为qureryset类型,

from app01 import models
序列化组建
第一种方式
class Book(APIView):
    def get(self,request):
        response={status:100,msg:None}
        books=models.Book.objects.all()
        # ll=[]
        # for book in books:
        #     ll.append({name:book.name,‘‘})
        ll=[ {name:book.name,price:book.price} for book in books]
        response[msg]=查询成功
        response[data]=ll
        return JsonResponse(response,safe=False)

        # return HttpResponse(get)
    def post(self,request):

        return HttpResponse(post)

2、第二种方式,用django子自带序列化组件serializers(Django内置的serializers(把对象序列化成json字符串),但是有个缺点不能定制化

from django.core import serializers


class Book(APIView):
    def get(self,request):
        # response={status:100,msg:None}
        books = models.Book.objects.all()
        ret = serializers.serialize("json", books)
        return HttpResponse(ret)

        # return HttpResponse(get)
    def post(self,request):

        return HttpResponse(post)

3、用drf自带的组件,建议的话新建个py在APP下,方便解耦,如myserial.py,为符合drf格式,里面新建个response类,见下

    -1 导入:from rest_framework import serializers
    -2 写一个类(名字任意),继承serializers.Serializer
        class BookSer(serializers.Serializer):
            nid=serializers.IntegerField()
            name3=serializers.CharField(source=name)
            price=serializers.CharField()
            # publish_date = serializers.DateField()
            publish_date = serializers.CharField()
            # publish=serializers.CharField(source=publish.email)
            publish=serializers.CharField(source=publish.name)
            xxx=serializers.CharField(source=test)
    -3 如果不指定source,字段名,必须跟数据库列名一致
    -4 source--》既可以指定数据属性,又可以指定方法属性,可以写(publish.name)
    -5 使用:
        -查询出要序列化的数据:books = models.Book.objects.all()
        -ret=myserial.BookSer(books,many=True)-----》多条(queryset对象),必须指定many=True
        -ret=myserial.BookSer(books,many=False)-----》一条(Book对象),必须指定many=False
    -6 aa=serializers.SerializerMethodField()
        -必须配套一个方法(get_aa(self,obj)),方法返回结果,会赋给aa
        -在方法内部,可以继续用序列化组件

myserial.py

from rest_framework import serializers

class BookSer(serializers.Serializer):
    nid=serializers.IntegerField()
    name3=serializers.CharField(source=name)
    price=serializers.CharField()
    # publish_date = serializers.DateField()
    publish_date = serializers.CharField()
    # publish=serializers.CharField(source=publish.email)
    publish=serializers.CharField(source=publish.name)
    xxx=serializers.CharField(source=test)
    # authors=serializers.CharField(source=authors.all)
    # SerializerMethodField,可以写一个方法方法名叫:get_字段名字,方法返回值,会赋给authors
    aa=serializers.SerializerMethodField()
    # def get_authors(self,obj):
    #     authors=obj.authors.all()
    #     # ll=[ author.name for author in authors]
    #     ll=[ {name:author.name,age:author.age} for author in authors]
    #     return ll
    def get_aa(self, obj):
        authors = obj.authors.all()
        # ll=[ author.name for author in authors]
        ser=AuthorSer(authors,many=True)
        return ser.data

models.py

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)

    publish = models.ForeignKey(to=Publish,to_field=nid,on_delete=models.CASCADE)
    authors=models.ManyToManyField(to=Author)

    def test(self):
        return ttttttt
    def __str__(self):
        return self.name

使用,为符合drf格式,里面新建个response类,@property让类方法变属性,不需要(),直接点+属性就ok了

class MyResponse():
    def __init__(self):
        self.status = 100
        self.msg = None

    @property
    def get_dic(self):
        return self.__dict__from app01 import myserial
class Book(APIView):
    queryset=models.Book.objects.all()
    serializer_class=myserial.BookSer
    def get(self,request):
        response=MyResponse()
        # 多条
        # books = models.Book.objects.all()
        # ret=myserial.BookSer(books,many=True)
        # 一条
        book = self.queryset
        # ret = myserial.BookSer(book, many=False)
        ret = self.serializer_class(instance=book, many=True)
        response.msg=查询成功
        response.data=ret.data
        return JsonResponse(response.get_dic,safe=False)

        # return HttpResponse(get)
    def post(self,request):
   
 # return HttpResponse(‘post‘)

4、若要进行多对多的查询,book和author,可以用SerializerMethodField方法

   -6 aa=serializers.SerializerMethodField()
        -必须配套一个方法(get_aa(self,obj)),方法返回结果,会赋给aa
        -在方法内部,可以继续用序列化组件

如下

class BookSer(serializers.Serializer):
    nid=serializers.IntegerField()
    name3=serializers.CharField(source=name)
    price=serializers.CharField()
    # publish_date = serializers.DateField()
    publish_date = serializers.CharField()
    # publish=serializers.CharField(source=publish.email)
    publish=serializers.CharField(source=publish.name)
    xxx=serializers.CharField(source=test)
    # authors=serializers.CharField(source=authors.all)
    # SerializerMethodField,可以写一个方法方法名叫:get_字段名字,方法返回值,会赋给authors
    aa=serializers.SerializerMethodField()
    # def get_authors(self,obj):
    #     authors=obj.authors.all()
    #     # ll=[ author.name for author in authors]
    #     ll=[ {name:author.name,age:author.age} for author in authors]
    #     return ll
    def get_aa(self, obj):
        authors = obj.authors.all()
        # ll=[ author.name for author in authors]
        ser=AuthorSer(authors,many=True)
        return ser.data


class AuthorSer(serializers.Serializer):
    id=serializers.IntegerField(source=nid)
    age=serializers.CharField()
    name=serializers.CharField()

四 序列化组件之serializers.ModelSerializer

    -用法同Serializer
    -不同点:
        class BookSer(serializers.ModelSerializer):
            class Meta:
                # 指定要序列号的表模型是book
                model=models.Book
                fields=__all__
                exclude=[nid]
                depth=1

例子如下

from app01 import models
class BookSer(serializers.ModelSerializer):
    class Meta:
        # 指定要序列号的表模型是book
        model=models.Book
        # 把所有字段都序列化
        # fields=__all__
        # 可以传列表,指定取几个
        # fields=[name,authors,publish]
        # 除了nid都查
        exclude=[authors]
        #fields和exclude不能同时用
        # depth指定深度,个人建议最多用3
        # depth=2

五 序列化组件的字段校验和反序列化功能

序列化组件是将对象序列化成字典,但是前台post提交的json数据需要转成字典,再反序列化成对象,最后save()方法才能保存在数据里,需要反序列功能

    -只有:ModelSerializer,能直接保存
    - def post(self,request):
        print(request.data)
        #生成一个序列化对象 
        ser=myserial.BookSer(data=request.data)
        #判断字段是否校验通过
        if ser.is_valid():
        #通过,直接保存
            ser.save()
        else:
            #错误信息        
            print(ser.errors)

        return HttpResponse(post)


from app01 import models
class BookSer(serializers.ModelSerializer):
class Meta:
# 指定要序列号的表模型是book
model=models.Book
exclude=[‘authors‘]

如下

 def post(self,request):
        # print(request.data)
        ser=myserial.BookSer(data=request.data)
        if ser.is_valid():
            ser.save()
            return HttpResponse(成功)
        else:
            print(ser.errors)

            return JsonResponse(ser.errors)

六 序列化组件局部校验和全局校验

 

    -局部校验
     name=serializers.CharField()
     def validate_name(self,value):
        if value.startswith(sb):
            raise ValidationError(不能以sb开头)
        else:
            return value
    -全局校验
        def validate(self,value):
            print(type(value))
            print(value)
            name=value.get(name)
            price=value.get(price)
            if name!=price:
                raise ValidationError(书名和价格不相等)
            else:

                return value

如下

from rest_framework.exceptions import ValidationError
from app01 import models
class BookSer(serializers.ModelSerializer):
    class Meta:
        # 指定要序列号的表模型是book
        model=models.Book
        # 把所有字段都序列化
        # fields=__all__
        # 可以传列表,指定取几个
        # fields=[name,authors,publish]
        # 除了nid都查
        exclude=[authors]
        #fields和exclude不能同时用
        # depth指定深度,个人建议最多用3
        # depth=2
    局部校验
    name=serializers.CharField(error_messages={required:该字段必填})
    def validate_name(self,value):
        if value.startswith(sb):
            raise ValidationError(不能以sb开头)
        else:
            return value
    全局校验
    def validate(self,value):
        print(type(value))
        print(value)
        name=value.get(name)
        price=value.get(price)
        if name!=price:
            raise ValidationError(书名和价格不相等)
        else:

            return value

views,主要验证前台post提交数据的局部和全局验证

from app01 import myserial
class Book(APIView):
    queryset=models.Book.objects.all()
    serializer_class=myserial.BookSer
    def get(self,request):
        response=MyResponse()
        # 多条
        # books = models.Book.objects.all()
        # ret=myserial.BookSer(books,many=True)
        # 一条
        book = self.queryset
        # ret = myserial.BookSer(book, many=False)
        ret = self.serializer_class(instance=book, many=True)
        response.msg=查询成功
        response.data=ret.data
        return JsonResponse(response.get_dic,safe=False)

        # return HttpResponse(get)
    def post(self,request):
        # print(request.data)
        ser=myserial.BookSer(data=request.data)
        if ser.is_valid():
            ser.save()
            return HttpResponse(成功)
        else:
            print(ser.errors)

            return JsonResponse(ser.errors)

七、符合drf的视图类基本写法

1、views.py


class MyResponse():
def __init__(self):
self.status = 100
self.msg = None

@property
def get_dic(self):
return self.__dict__

class
BookDetail(APIView): def get(self,request,id): response=MyResponse() ret=models.Book.objects.filter(pk=id).first() ser=myserial.BookSer(instance=ret,many=False) response.msg=查询成功 response.data=ser.data return JsonResponse(response.get_dic,safe=False) def put(self,request,id): # 修改 response=MyResponse() book=models.Book.objects.filter(pk=id).first() ser=myserial.BookSer(instance=book,data=request.data) if ser.is_valid(): # 可以新增,可以修改 ser.save() print(ser.data) print(type(ser.instance)) response.msg=修改成功 response.data=ser.data else: response.msg = 修改失败 response.status = 101 response.data=ser.errors return JsonResponse(response.get_dic,safe=False) def delete(self,request,id): ret=models.Book.objects.filter(pk=id).delete() return HttpResponse(删除成功)

2、序列化组件

url(r^books/(?P<pk>d+)/, views.BookDetail.as_view()),

from app01 import models
class BookSer(serializers.ModelSerializer):
class Meta:
# 指定要序列号的表模型是book
model=models.Book
exclude=[‘authors‘]

 




























以上是关于RESTful规范的主要内容,如果未能解决你的问题,请参考以下文章

restful 架构风格的curd(增删改查)

php Yoast SEO规范输出的代码片段

php Yoast SEO规范输出的代码片段

RESTful规范

Restful规范

RESTful规范