1、入门
1.1 参考blog
官方文档:http://www.django-rest-framework.org/tutorial/quickstart/#quickstart
yuan的Blog:http://www.cnblogs.com/yuanchenqi/articles/8719520.html
alice的Blog:https://www.cnblogs.com/alice-bj/p/9228402.html
1.2 restful协议
restful协议
---- 一切皆是资源,操作只是请求方式
----book表增删改查
/books/ books
/books/add/ addbook
/books/(d+)/change/ changebook
/books/(d+)/delete/ delbook
----book表增删改查 url里面不能出现动词!!
/books/ -----get books ----- 返回当前所有数据
/books/ -----post books ----- 返回提交数据
/books/(d+)-----get bookdetail ----- 返回当前查看的单条数据
/books/(d+)-----put bookdetail ----- 返回更新数据
/books/(d+)-----delete bookdetail ----- 返回空
1.3 安装
pip install django
pip install djangorestframework
2. 序列化方法
序列化是什么? QuerySet-->list-->json
2.1 restdemo
model
from django.db import models class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish",on_delete=models.CASCADE) 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
url
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('publishes/', views.PublishView.as_view()), ]
view
from django.shortcuts import render,HttpResponse # Create your views here. from django.views import View from .models import Publish import json class PublishView(View): def get(self,request): # QuerySet-->vales取值--->list--->json publish_list = list(Publish.objects.all().values("name","email")) return HttpResponse(json.dumps(publish_list)) def post(self,request): pass
database
data生成与迁移
python manage.py makemigrations
python manage.py migrate
运行django项目
2.2 方式1 :list()
2.3 方式2:model_to_dict(obj)
2.4 方式3:django serializers
2.5 方式4 :restframework serializers (推荐)
2.6 code
from django.shortcuts import render,HttpResponse # 为queryset,model对象做序列化 from rest_framework import serializers # rest_framework的序列化组件 class PublishSerializers(serializers.Serializer): # 对哪些字段序列化 name = serializers.CharField() email = serializers.EmailField() from django.views import View from .models import Publish import json class PublishView(View): def get(self,request): # QuerySet--->list--->json # 序列化方式1 # list() # publish_list = list(Publish.objects.all().values("name","email")) #return HttpResponse(json.dumps(publish_list)) # 序列化方式2 # model对象转换为dict # from django.forms.models import model_to_dict # publish_list = Publish.objects.all() # temp = [] # for obj in publish_list: # # temp.append(model_to_dict(obj)) # # # temp.append({ # # "name":obj.name, # # "email":obj.email # # }) # # return HttpResponse(temp) # # 序列化方式3 # django的序列化组件 # from django.core import serializers # publish_list = Publish.objects.all() # ret = serializers.serialize("json",publish_list) # # return HttpResponse(ret) # 序列化方式4 rest_framework的序列化组件 publish_list = Publish.objects.all() ret = PublishSerializers(publish_list,many=True) return HttpResponse(ret.data) def post(self,request): pass
3.取数据:APIView
3.1 Django的原生request
1.get取数据
2.post取数据
3. request实质就是http报文头
(1)Django的原生request: 浏览器 ------------- 服务器 "GET url?a=1&b=2 http/1.1 user_agent:Google contentType:urlencoded " "POST url http/1.1 user_agent:Google contentType:urlencoded a=1&b=2" request.body: a=1&b=2 request.POST: if contentType:urlencoded: a=1&b=2----->{"a":1,"b":2}
4.发送json
3.2 原生request源码
content-type
3.3 restframework下的 APIView
1. 新的request 取数据
2. urlencoded类型的data
3. get请求
3.3 APIView源码
1. 继承了基本的View
2. APIView下的dispatch
3.4 view代码
get:
request._request ( 原request )
request.GET == request._request.GET
post:
request.data ( 得到 json 数据,也可得到 urlencode 数据)
都是 rest_framework APIView 的功劳,
如果使用 View , request.post( 只能得到 urlencode 的数据,不能得到 json 数据,只能从 request.body 中取)
from django.shortcuts import render,HttpResponse
from django.views import View
from rest_framework.views import APIView # class PublishView(View): # 原生View class PublishView(APIView): # APIView def get(self,request): # 取数据 print("request.data ",request.data) print("request.data type ",type(request.data)) print(request._request.GET) #旧的request print(request.GET) return HttpResponse("123") def post(self,request): # 取数据 # 1 原生reqeust支持的操作 # print("post...",request.POST) # print("body...",request.body) # print(type(request)) # <class 'django.core.handlers.wsgi.WSGIRequest'> # from django.core.handlers.wsgi import WSGIRequest # 2 新的reqeust支持的操作 # request._request.POST # 取出旧的request print("request.data ",request.data) print("request.data type ",type(request.data)) return HttpResponse("POST")
4. 序列化字段:Serializer
4.1 准备demo
1. views
from django.shortcuts import render,HttpResponse # 为queryset,model对象做序列化 from rest_framework import serializers # rest_framework的序列化组件 class PublishSerializers(serializers.Serializer): # 对哪些字段序列化 name = serializers.CharField() email = serializers.EmailField() # 为Book做序列化 class BookSerializers(serializers.Serializer): title = serializers.CharField(max_length=32) price = serializers.IntegerField() pub_date = serializers.DateField() from rest_framework.views import APIView class PublishView(APIView): # APIView def get(self,request): return HttpResponse("123") def post(self,request): return HttpResponse("POST") from .models import Book class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookSerializers(book_list,many=True) return HttpResponse(bs.data) def post(self,request): pass
2. database
Question报错:
return datetime.date(*map(int, val.split(b"-")))
OverflowError: Python int too large to convert to C long
原因:估计是sqlite中datetime的问题
解决办法:创建superuser,进入admin页面,添加书籍,生成到数据库的data
4.2 响应器 response
""" 响应器
针对 不同得访问者 浏览器 postman 做不同得处理
只有浏览器,用户 会给一个页面!!
几种请求方式
get post
get put delete
"""
1.Response继承了HttpResponse
2. restframework就是一个app,需要注册
3.get得到的data实质
4.3 默认打印__str__定制的字段
# publish = serializers.CharField() # 默认打印 __str__定义的字段名 publish = serializers.CharField(source="publish.name")
5. 如何一对多显示
# 一对多 # authors = serializers.CharField(source="authors.all") #"authors": "<QuerySet [<Author: alex>, <Author: yuan>]>" authors = serializers.SerializerMethodField() def get_authors(self,obj): temp = [] for obj in obj.authors.all(): temp.append(obj.name) return temp
4.4 序列化的过程
""" 序列化BookSerializers(book_list,many=True)过程 temp = [] for obj in book_list: temp.append({ "title":obj.title, "price":obj.price, "pub_date":obj.pub_date, "publish":str(obj.publish), # obj.publish.name "authors":get_authors(obj) }) return HttpResponse(temp) """
4.5 code代码
view
from django.shortcuts import render,HttpResponse # 为queryset,model对象做序列化 from rest_framework import serializers # rest_framework的序列化组件 class PublishSerializers(serializers.Serializer): # 对哪些字段序列化 name = serializers.CharField() email = serializers.EmailField() # 为Book做序列化 class BookSerializers(serializers.Serializer): title = serializers.CharField(max_length=32) price = serializers.IntegerField() pub_date = serializers.DateField() # publish = serializers.CharField() # 默认打印 __str__定义的字段名 publish = serializers.CharField(source="publish.name") # 一对多 # authors = serializers.CharField(source="authors.all") #"authors": "<QuerySet [<Author: alex>, <Author: yuan>]>" authors = serializers.SerializerMethodField() def get_authors(self,obj): temp = [] for obj in obj.authors.all(): temp.append(obj.name) return temp from rest_framework.views import APIView class PublishView(APIView): # APIView def get(self,request): return HttpResponse("123") def post(self,request): return HttpResponse("POST") from .models import Book from rest_framework.response import Response class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookSerializers(book_list,many=True) # return HttpResponse(bs.data) return Response(bs.data) # Response继承HttpResponse def post(self,request): pass
5.序列化模型:ModelSerializers
5.1 以Book为例
from django.shortcuts import render,HttpResponse from .models import Book from rest_framework import serializers # rest_framework的序列化组件 from rest_framework.views import APIView from rest_framework.response import Response class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Book fields = '__all__' class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookModelSerializers(book_list,many=True) return Response(bs.data) # Response继承HttpResponse def post(self,request): pass class PublishSerializers(serializers.Serializer): # 对哪些字段序列化 name = serializers.CharField() email = serializers.EmailField() class PublishView(APIView): # APIView def get(self,request): return HttpResponse("123") def post(self,request): return HttpResponse("POST")
5.2 get请求:显示书籍,自定制
自定制字段的source
# 如何显示字段 publish = serializers.CharField(source="publish.name") # 原生的create不接受自定制,需要重写create方法 authors = serializers.SerializerMethodField(source="authors.all") def get_authors(self,obj): temp = [] for obj in obj.authors.all(): temp.append(obj.name) return temp
5.3 post请求,保存书籍
1. 取消自定制的,source
create方法中没有source自定义
def post(self,request): # post请求的数据 bs = BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # create方法 return Response(bs.data) else: return Response(bs.errors)
2. 源码create
3. 发送json数据,提交到database
5.4 重写create方法
原生的create不接受自定制,需要重写create方法
class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Book fields = '__all__' # 如何显示字段 publish = serializers.CharField(source="publish.name") # 原生的create不接受自定制,需要重写create方法 # 重写create方法 # 不接受自定制字段,source def create(self, validated_data): print("validated_data...",validated_data) book = Book.objects.create(title=validated_data['title'],price=validated_data['price'], pub_date=validated_data['pub_date'],publish_id=validated_data['publish']['name']) book.authors.add(*validated_data['authors']) return book
6.单条数据(get,put,delete)
6.1 解耦:新建serializer.py
1.serializer.py
from rest_framework import serializers # rest_framework的序列化组件 from .models import Book class PublishSerializers(serializers.Serializer): name = serializers.CharField() email = serializers.EmailField() class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Book fields = '__all__'
2. view.py
from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.response import Response from app01.serilizer import BookModelSerializers # 从serilizer中导入 from .models import Book class PublishView(APIView): # APIView def get(self,request): return HttpResponse("123") def post(self,request): return HttpResponse("POST") class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookModelSerializers(book_list,many=True) return Response(bs.data) # Response继承HttpResponse def post(self,request): # post请求的数据 bs = BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # create方法 return Response(bs.data) else: return Response(bs.errors)
6.2 单条数据demo
urls:正则表达式用re_path
from django.contrib import admin from django.urls import path from django.urls import re_path # 正则表达式的 from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('publishes/', views.PublishView.as_view()), # view(request)====> APIView:dispatch() path('books/', views.BookView.as_view()), re_path(r'books/(d+)/$', views.BookDetailView.as_view()), ]
view
from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.response import Response from app01.serilizer import BookModelSerializers # 从serilizer中导入 from .models import Book class PublishView(APIView): # APIView def get(self,request): return HttpResponse("123") def post(self,request): return HttpResponse("POST") class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookModelSerializers(book_list,many=True) return Response(bs.data) # Response继承HttpResponse def post(self,request): # post请求的数据 bs = BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # create方法 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,id): # 获取某本书的信息 book = Book.objects.filter(pk=id).first() # 过滤单挑data bs = BookModelSerializers(book) return Response(bs.data) def put(self,rquest,id): # 更新某本书的字段 book = Book.objects.filter(pk=id).first() bs = BookModelSerializers(book,data=rquest.data) if bs.is_valid(): bs.save() # 实质create方法 return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): # 删除某条数据 Book.objects.filter(pk=id).delete() return Response("Delete 第%s本书成功"%(id))
get取数据
更新data
{ "title": "野兽绅士","price": 88, "pub_date": "2019-07-23","publish": 2,"authors": [1,2]}
delete
7.超链接API
7.1 配置publish为单条数据
urls
from django.contrib import admin from django.urls import path from django.urls import re_path # 正则表达式的 from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('publishes/', views.PublishView.as_view()), # view(request)====> APIView:dispatch() re_path(r'publishes/(d+)/$', views.PublishDetailView.as_view()), path('books/', views.BookView.as_view()), re_path(r'books/(d+)/$', views.BookDetailView.as_view()), ]
serilizer
from rest_framework import serializers # rest_framework的序列化组件 from .models import Book,Publish class PublishSerializers(serializers.Serializer): name = serializers.CharField() email = serializers.EmailField() class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Book fields = '__all__' class PublishModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Publish fields = '__all__'
views
from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.response import Response from app01.serilizer import BookModelSerializers # 从serilizer中导入 from app01.serilizer import PublishModelSerializers # from .models import Book,Publish class PublishView(APIView): # APIView def get(self,request): publish_list = Publish.objects.all() ps = PublishModelSerializers(publish_list,many=True) return Response(ps.data) def post(self,request): ps = PublishModelSerializers(data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) class PublishDetailView(APIView): def get(self,request,id): # 获取某publish的信息 publish = Publish.objects.filter(pk=id).first() ps = PublishModelSerializers(publish) return Response(ps.data) def put(self,request,id): # 更新某pub的信息 publish = Publish.objects.filter(pk=id).first() ps = PublishModelSerializers(publish,data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) def delete(self,request,id): # 删除某天publish Publish.objects.filter(pk=id).delete() return Response("Delete 第%s个出版社"%(id)) class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookModelSerializers(book_list,many=True) return Response(bs.data) # Response继承HttpResponse def post(self,request): # post请求的数据 bs = BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # create方法 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,id): # 获取某本书的信息 book = Book.objects.filter(pk=id).first() # 过滤单挑data bs = BookModelSerializers(book) return Response(bs.data) def put(self,rquest,id): # 更新某本书的字段 book = Book.objects.filter(pk=id).first() bs = BookModelSerializers(book,data=rquest.data) if bs.is_valid(): bs.save() # 实质create方法 return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): # 删除某条数据 Book.objects.filter(pk=id).delete() return Response("Delete 第%s本书成功"%(id))
7.2 配置超链接
1.效果图
2.urls
3.serilizer中,定义超链接
4.view中id修改pk
5. view中调用 Serializers的地方,重新什么request
7.3 code代码
urls
from django.contrib import admin from django.urls import path from django.urls import re_path # 正则表达式的 from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('publishes/', views.PublishView.as_view()), # view(request)====> APIView:dispatch() re_path(r'publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(),name="detailPublish"), path('books/', views.BookView.as_view()), re_path(r'books/(d+)/$', views.BookDetailView.as_view()), ]
views
from django.shortcuts import render,HttpResponse from rest_framework.views import APIView from rest_framework.response import Response from app01.serilizer import BookModelSerializers # 从serilizer中导入 from app01.serilizer import PublishModelSerializers # from .models import Book,Publish class PublishView(APIView): # APIView def get(self,request): publish_list = Publish.objects.all() ps = PublishModelSerializers(publish_list,many=True) return Response(ps.data) def post(self,request): ps = PublishModelSerializers(data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) class PublishDetailView(APIView): def get(self,request,pk): # 获取某publish的信息 publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish) return Response(ps.data) def put(self,request,pk): # 更新某pub的信息 publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish,data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else: return Response(ps.errors) def delete(self,request,pk): # 删除某天publish Publish.objects.filter(pk=pk).delete() return Response("Delete 第%s个出版社"%(pk)) class BookView(APIView): def get(self,request): book_list = Book.objects.all() bs = BookModelSerializers(book_list,many=True,context={'request':request}) return Response(bs.data) # Response继承HttpResponse def post(self,request): # post请求的数据 bs = BookModelSerializers(data=request.data,context={'request':request}) if bs.is_valid(): print(bs.validated_data) bs.save() # create方法 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,id): # 获取某本书的信息 book = Book.objects.filter(pk=id).first() # 过滤单挑data bs = BookModelSerializers(book,context={'request':request}) return Response(bs.data) def put(self,request,id): # 更新某本书的字段 book = Book.objects.filter(pk=id).first() bs = BookModelSerializers(book,data=request.data,context={'request':request}) if bs.is_valid(): bs.save() # 实质create方法 return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): # 删除某条数据 Book.objects.filter(pk=id).delete() return Response("Delete 第%s本书成功"%(id))
serilizer
from rest_framework import serializers # rest_framework的序列化组件 from .models import Book,Publish class PublishSerializers(serializers.Serializer): name = serializers.CharField() email = serializers.EmailField() class BookModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Book fields = '__all__' # 显示超链接,在Book下的publish publish = serializers.HyperlinkedIdentityField( view_name="detailPublish", # 别名 含正则表达式 lookup_field="publish_id", # publish_id替换pk lookup_url_kwarg="pk", # url中的pk ) class PublishModelSerializers(serializers.ModelSerializer): # ModelSerializer class Meta: model = Publish fields = '__all__'
8. 今日总结
day 96 CBV与FBV restful协议 ---- 一切皆是资源,操作只是请求方式 ----book表增删改查 /books/ books /books/add/ addbook /books/(d+)/change/ changebook /books/(d+)/delete/ delbook ----book表增删改查 /books/ -----get books ----- 返回当前所有数据 /books/ -----post books ----- 返回提交数据 /books/(d+)-----get bookdetail ----- 返回当前查看的单条数据 /books/(d+)-----put bookdetail ----- 返回更新数据 /books/(d+)-----delete bookdetail ----- 返回空 class Books(View): def get(self,request): pass # 查看所有书籍 def post(self,request): pass # 添加书籍 class BooksDetail(View): def get(self,request,id): pass # 查看具体书籍 def put(self,request,id): pass # 更新某本书籍 def delete(self,request,id): pass # 删除某本书籍 restframework(Django) ----针对数据:json (1)Django的原生request: 浏览器 ------------- 服务器 "GET url?a=1&b=2 http/1.1 user_agent:Google contentType:urlencoded " "POST url http/1.1 user_agent:Google contentType:urlencoded a=1&b=2" request.body: a=1&b=2 request.POST: if contentType:urlencoded: a=1&b=2----->{"a":1,"b":2} (2)restframework 下的APIView: (3) class PublishSerializers(serializers.Serializer): name=serializers.CharField() email=serializers.CharField() PublishSerializers(queryset,many=true) PublishSerializers(model_obj) 总结: 1 reuqest类----源码 2 restframework 下的APIView--源码 url(r'^books/$', views.BookView.as_view(),name="books")# View下的view books/一旦被访问: view(request) ------APIView: dispatch() 3 def dispatch(): 构建request对象 self.request=Request(request) self.request._request self.request.GET # get self.request.data # POST PUT 分发----if get请求: if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) # self.get(request, *args, **kwargs) return response 4 序列化类 # from django.core import serializers # ret=serializers.serialize("json",publish_list) restframework下的序列类 BookModelSerializers 将queryset或者model对象序列成一json数据 bs=BookModelSerializers(book_list,many=True,context={'request': request}) bs=BookModelSerializers(book,context={'request': request}) 还可以做校验数据,json-------》queryset/model-->记录 bs=BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # 重写create方法 5 操作数据: 以Book表为例 class BookView(APIView): # 查看所有书籍 def get(self,request): book_list=Book.objects.all() bs=BookModelSerializers(book_list,many=True,context={'request': request}) return Response(bs.data) # 添加一本书籍 def post(self,request): # post请求的数据 bs=BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save()# create方法 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): # 查看一本书籍 def get(self,request,id): book=Book.objects.filter(pk=id).first() bs=BookModelSerializers(book,context={'request': request}) return Response(bs.data) # 更新一本书籍 def put(self,request,id): book=Book.objects.filter(pk=id).first() bs=BookModelSerializers(book,data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else: return Response(bs.errors) # 删除某一本书籍 def delete(self,request,id): Book.objects.filter(pk=id).delete() return Response() restframework 1 APIView 2 序列组件 3 视图、 4 组件(认证权限频率) 5 数据解析器 6 分页和Response