Restframework
这里先简单的介绍一下restful协议,Django REST framework 是一个强大且灵活的工具包,用以构建Web APIs,体现了一切皆是资源,操做只是请求方式前端
基于restful协议的框架有不少,Django下的restframework只是其中的一种,restful协议是一套开发的规范,url里不能有动做相关的词汇,好比add,edit,这些都经过用请求的方式来实现。python
安装数据库
pip3 install djangorestframework
注册django
INSTALLED_APPS = ( ... 'rest_framework', )
基本使用json
登陆认证restful
url(r'^login/$', views.LoginView.as_view(),name="login"),
def get_random_str(user): import hashlib,time ctime=str(time.time()) md5=hashlib.md5(bytes(user,encoding="utf8")) md5.update(bytes(ctime,encoding="utf8")) return md5.hexdigest() from .models import User class LoginView(APIView): def post(self,request): name=request.data.get("name") pwd=request.data.get("pwd") user=User.objects.filter(name=name,pwd=pwd).first() res = {"state_code": 1000, "msg": None} if user: random_str=get_random_str(user.name) token=Token.objects.update_or_create(user=user,defaults={"token":random_str}) res["token"]=random_str else: res["state_code"]=1001 #错误状态码 res["msg"] = "用户名或者密码错误" import json return Response(json.dumps(res,ensure_ascii=False))
认证类app
from .models import * class TokenAuth(BaseAuthentication): def authenticate(self,request): token = request.GET.get("token") token_obj = Token.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed("验证失败123!") else: return token_obj.user.name,token_obj.token
models.py
from django.db import models class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
urls.py框架
from django.conf.urls import url from django.contrib import admin from rest_demoimport views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^authors/$', views.AuthorsView.as_view()), url(r'^authors/(\d+)/$', views.AuthorsDetailView.as_view()), ]
serializer.pydom
from rest_framework import serializers from rest_demo import models class AuthorModelSerializers(serializers.ModelSerializer): class Meta: model = models.Author fields = '__all__'
views.py工具
from rest_demo import serializer from rest_framework.views import APIView from rest_framework.response import Response from rest_demo import models class AuthorsView(APIView): def get(self,request): ''' 查询全部做者 :param request: :return: ''' author_list = models.Author.objects.all() auts = serializer.AuthorModelSerializers(author_list,many=True)# 默认为False return Response(auts.data) # .data 拿json对象 def post(self,request): ''' 添加做者 :param request: :return: ''' auts = serializer.AuthorModelSerializers(data=request.data) if auts.is_valid(): auts.save() return Response(auts.data) return Response(auts.errors) class AuthorsDetailView(APIView): def get(self,request,id): ''' 查询单条做者 :param request: :param id: :return: ''' author = models.Author.objects.filter(pk=id).first() auts = serializer.AuthorModelSerializers(author) return Response(auts.data) def put(self,request,id): ''' 修改单条做者 :param request: :param id: :return: ''' author = models.Author.objects.filter(pk=id).first() auts = serializer.AuthorModelSerializers(instance=author,data=request.data) if auts.is_valid(): auts.save() return Response(auts.data) return Response(auts.errors) def delete(self,request,id): ''' 删除单条做者 :param request: :param id: :return: ''' models.Author.objects.filter(pk=id).delete() return Response()
url中
urlpatterns = [ url(r'^books/$', views.BookViewSet.as_view(),name="book_list"), url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"), url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"), url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"), ]
view视图中
class Books(View): def get(self,requset): pass #查看全部书籍 def post(self,request): pass #添加书籍 class BooksDetail(View): def get(self,request,id): pass #查看某一本书籍 def put(self,requset,id): pass #更新书籍 def delete(self,request,id): pass #删除书籍
在父类的基础上扩展,并执行父类方法
继承后调用父类的方法: 扩展后子类继续调用父类的方法: class LoginView(View): def dispatch(self,request,*arg,**kwargs): # 两种方式均可以 print('扩展父类方法') ret = super(LoginView,self).dispatch(self,request,*arg,**kwargs) ret = super().dispatch(self,request,*arg,**kwargs) return ret
序列化的方式,下列三种
model.py中
rom 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 model
view部分
from rest_framework.views import APIView from rest_framework.response import Response from .models import * from django.shortcuts import HttpResponse from django.core import serializers from rest_framework import serializers class BookSerializers(serializers.Serializer): title=serializers.CharField(max_length=32) price=serializers.IntegerField() pub_date=serializers.DateField() # 一对多核多对多须要咱们本身构建 publish=serializers.CharField(source="publish.name") #authors=serializers.CharField(source="authors.all") authors=serializers.SerializerMethodField() def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) return Response(bs.data)
上面能作的知识单纯的将queryset序列化,那么有没有可以既可以序列化对象传给前端,
又可以接受前端的数据而后更新到数据库呢?
ModelSerializer
modelserializer和modelform很相似,用法也很类似.
class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields="__all__" depth=1
提交post请求
def post(self,request,*args,**kwargs): bs=BookSerializers(data=request.data,many=False) if bs.is_valid(): # print(bs.validated_data) bs.save() return Response(bs.data) else: return Response(bs.errors)
重写save和create方法
class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields="__all__" # exclude = ['authors',] # depth=1 def create(self, validated_data): authors = validated_data.pop('authors') obj = Book.objects.create(**validated_data) obj.authors.add(*authors) return obj
单条数据的get和put请求
class BookDetailViewSet(APIView): def get(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj) return Response(bs.data) def put(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj,data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else: return Response(bs.errors)
咱们能够看到中间CBV的类继承了restframework的APIView,那么里面的继承关系,和流程是怎么样的呢?
url(r'^books/$', views.BookView.as_view(),name="books")#views.BookView.as_view()至关于 View下的view,用户访问执行view
也就至关于books/一旦被访问: view(request) 就执行APIView: dispatch()方法
在restframework的dispatch方法里干了什么事?
从新构建request对象
self.request=Request(request)
self.request._request
Django原生的request:
如何在重构的request对象里获取数据?
request.GET # get request.data # POST PUT delete
超连接API:Hyperlinked
class BookSerializers(serializers.ModelSerializer): publish= serializers.HyperlinkedIdentityField( view_name='publish_detail', #要找的url的别名 name lookup_field="publish_id", 关联的publish_id lookup_url_kwarg="pk") 对应URL中?P<pk> class Meta: model=Book fields="__all__" #depth=1
urls部分:
urlpatterns = [ url(r'^books/$', views.BookViewSet.as_view(),name="book_list"), url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"), url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"), url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"), ]