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




    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不允许出现动词,只有名词]

猜你喜欢

转载自www.cnblogs.com/vivian0119/p/11931363.html