django之restframework使用 (一)

Restframework

这里先简单的介绍一下restful协议,Django REST framework 是一个强大且灵活的工具包,用以构建Web APIs,体现了一切皆是资源,操作只是请求方式

基于restful协议的框架有很多,Django下的restframework只是其中的一种,restful协议是一套开发的规范,url里不能有动作相关的词汇,比如add,edit,这些都通过用请求的方式来实现。

安装

pip3 install djangorestframework

 注册

INSTALLED_APPS = (
    ...
    'rest_framework',
)
 

 基本使用

登录认证

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))

 认证类

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.py

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"),
]

 

posted @ 2019-02-20 00:19  离人怎挽_wdj  阅读(230)  评论(0编辑  收藏  举报