zoukankan      html  css  js  c++  java
  • 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"),
    ]
    

    I can feel you forgetting me。。 有一种默契叫做我不理你,你就不理我

  • 相关阅读:
    04_移动端-伪元素选择器
    03_移动端-结构伪类选择器
    02_移动端-属性选择器
    Dva+Antd创建React项目(一)
    Windows 10 使用打印机扫描
    中间件-redis
    #期望dp#51nod 2015 诺德街
    Codeforces Round #685 (Div. 2)
    USACO 4.2
    #保序回归问题,单调栈,二分#洛谷 5294 [HNOI2019]序列
  • 原文地址:https://www.cnblogs.com/weidaijie/p/10404236.html
Copyright © 2011-2022 走看看