• Django学习之四(序列化与视图三部曲)


    一、课程回顾

      1.cookie 与 session

      cookie:会化跟踪技术,HTTP协议是无状态协议,也就是说每个请求都是独立的!无法记录前一次请求的状态。但HTTP协议中可以使用Cookie来完成会话跟踪!在Web开发中,使用session来完成会话跟踪,session底层依赖Cookie技术。 

      cookie是保存在每一个浏览器(客户端)上的一个(key,values)结构的文件。

        key1:客户端上具体某一个浏览器;

        key2:每一个浏览器都维持着一个类似于字典{}的结构;

        key3:浏览器会针对每一个cookie

      注:redirect(重定向),第一次get请求,返回页面;第二次发登录请求,点击submit按钮,浏览器新发一个请求,回到客户端(通过状态码:3开头)

    •  Cookie大小上限为4KB; 
    •  一个服务器最多在客户端浏览器上保存20个Cookie; 
    •  一个浏览器最多保存300个Cookie;  

      

      语法:

        写cookie:

          obj=HttpResponse()

          obj.set_cookie("key","value",10)

        读cookie:

          request.COOKIES("key")

      session:将信息保存在服务器

        写session:

          request.session["user_id"]=1

          """

            1.生成随机字符串:12344546fgdfgd;

            2.在django-session表中创建一条记录

              session-key      session-data

              2344546fgdfgd      {"user_id":1,"name","alex"}

            3.res.set_cookie("session_id","2344546fgdfgd")  --->建立联系的钥匙

          """

        读session:

          user_id=request.session["user_id"]

         """

            1.random_str=request.COOKIES.get("session_id");

            2.在django-session表中查询记录

            3.django-session.objects.filter(session-key=random_str).first().session-data.get()  -->需要序列化转换(json[loads,dumps])

          """

    二、CBV,--》序列化组件

      1.前后端分离:后端仅返回前端所需的数据,不再渲染HTML页面,不再控制前端的效果。至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页的处理方式,App有App的处理方式,但无论哪种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据即可。

      在前后端分离的应用模式中 ,前端与后端的耦合度相对较低。

      在前后端分离的应用模式中,我们通常将后端开发的每个视图都称为一个接口,或者API,前端通过访问接口来对数据进行增删改查。

      2.CBV 与 FBV

        FBV:  function based view

        CBV: class  based view 

        例子:

          path('index/', views.IndexView.as_view()),

          path('index/', View.view()),    --->class IndexView(View)

            用户发送/index/请求,执行view(request)

            def view(request, *args, **kwargs):

                return self.dispatch(request, *args, **kwargs)

            def dispatch(self, request, *args, **kwargs):

                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

                return handler(request, *args, **kwargs)

       写代码:1.写注释,规范;

       看源码:1.看不懂,先过;2.找自己关注的重点;3.有迹可循,先找类对象;

    三、DRF:Django rest framework

      1.RESTful

        a. REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”

        b.REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态

        c.REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”

        d.所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性

        e.对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

        restful:

           http://127.0.0.1:8000/books/   ---get(查)--->post(添加)------------->      

           http://127.0.0.1:8000/books/1   ---put/patch(更新数据)--->---delete(删除)--->[URL不允许出现动词,只有名词]

        method

    • GET      :从服务器取出资源(一项或多项)
    • POST    :在服务器新建一个资源
    • PUT      :在服务器更新资源(客户端提供改变后的完整资源)
    • PATCH  :在服务器更新资源(客户端提供改变的属性)
    • DELETE :从服务器删除资源

    状态码:

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    
    更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

       2.rest framework项目例子(在数据库中添加数据,切记,一定要先添加无关键字和外键的表,不能先添加有关键字的表-----》很重要):

    #序列化器1  

    models:

    from 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", 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
      views:
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app01 import models
    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):
    GET请求
    def get(self, request, *args, **kwargs):
    book_list = models.Book.objects.all()
    print(book_list, "book_list")
    # # 序列化方式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:[序列化2不需要添加BookSerializers,且引用的是:django.core.serializers, 其他的serializers要注释,不然无法找到:serializers.serialize, rest_framework下只有serializers]
            # data = serializers.serialize("json", book_list)
    # return HttpResponse(data)

    # 序列化方式3[使用的是:
    from rest_framework import serializers 中+ BookSerializers(serializers.Serializer)序列化器 ]:
            bs=BookSerializers(book_list, many=True)
    print(bs.data)
    # return HttpResponse("DEFGET is ok")
    return Response(bs.data)
    POST请求

    def post(self,request,*args,**kwargs):
          print("POST", request.POST)
          print("data", request.data)

          #2。添加数据到数据库
          bs = BookSerializers(data=request.data, many=False)
          #校验数据,校验成功,就保存,失败就返回bs.errors
          if bs.is_valid():
          pass
          else:
          return Response(bs.errors)


    return HttpResponse("DEFPOST is ok")
    #序列化器2(序列化组件)
    class BookSerializers(serializers.ModelSerializer):
    # 一对多
    publish = serializers.CharField(source="publish.email")
    # 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 Meta:
    model = Book
    fields = "__all__"
    # # fields = ["title", "price"]
    # exclude = ["price"]
    PUT请求
    urls:
    #修改+删除必须加ID
    re_path('books/(d+)', views.SBookViewSet.as_view()),
    【re_path和path的作用都是一样的。只不过re_path是在写url的时候可以用正则表达式,功能更加强大。】
    views:
    class SBookViewSet(APIView):
    #put与 delete和get与post分开,是因为put(或delete) 必须要传ID进去,新的类要传2哥参数,而BookView只需要传一个参数,所以访问的时候无法确定在哪一个类中,因此需要通过另起一个类来区分

    def put(self, request, id, *args, **kwargs):
    #1.获取数据
    update_data = request.data
    #2.更新数据库
    update_book = Book.objects.filter(pk = id).first()
    bs = BookSerializers(instance=update_book, data = update_data)
    if bs.is_valid():
    #单条记录
    bs.save()
    return Response(bs.data)
    #3.返回更新后的数据
    return Response(bs.errors)

    postman传入json数据格式

      {
        "authors": [2,3],
        "title": "C---",
        "price": 119,
        "pub_date": "2015-12-15",
        "publish": 1
        }

    delete请求

    def delete(self, request, id, *args, **kwargs):
    del_book= Book.objects.filter(pk=id).first()
    del_book.delete()
       return Response("")
     四、视图三部曲(mixin编写视图)
    publish(mixin)
    urls:
    path('publish/', views.PublishViewSet.as_view()),
    #必须添加有名分组
    re_path('publish/(?P<pk>d+)', views.SPublishViewSet.as_view()),
    views:
    #作者序列化组件
    class AuthorSerializers(serializers.ModelSerializer):
    class Meta:
    model = Author
    fields = "__all__"
    from rest_framework import mixins
    from rest_framework import generics

    #多重继承
    class PublishViewSet(mixins.ListModelMixin,
    mixins.CreateModelMixin,
    generics.GenericAPIView):
    #queryset被GenericAPIView封装在的get_queryset的函数下(源码)
    queryset = Publish.objects.all()

    #序列化器
    serializer_class = PublishSerializers

    def get(self, request, *args, **kwargs):
    #list封装在ListModelMixin这个方法类
    return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
    return self.list(request, *args, **kwargs)


    class SPublishViewSet(mixins.RetrieveModelMixin,
    mixins.DestroyModelMixin,
    mixins.UpdateModelMixin,
    generics.GenericAPIView):
    queryset = Publish.objects.all()

    # 序列化器
    serializer_class = PublishSerializers
      #这里与不再使用list方法
    def get(self, request, *args, **kwargs):
    return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
    return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
    return self.destroy(request, *args, **kwargs)
    #最终版
    urls:
    #最终版本封装
    path('author/', views.AuthorViewSet.as_view({"get" : "list", "post" : "create"})),
    re_path('author/(?P<pk>d+)', views.AuthorViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
    })),
    views:
    from rest_framework import viewsets

    class AuthorViewSet(viewsets.ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializers




  • 相关阅读:
    Mysql5.7主主互备安装配置
    一个简单有效的kubernetes部署案例
    kubernetes应用部署原理
    在线电路编程 (ICP)
    N76E003系统时钟
    说说UART(转)
    串行通信中 同步通信和异步通信的区别及使用情况(转)
    串行通讯与并行通讯区别
    定时器2及输入捕获
    N76E003之定时器3
  • 原文地址:https://www.cnblogs.com/vivian0119/p/11931363.html
Copyright © 2020-2023  润新知