GVKun编程网logo

Django--- 请求、响应(django请求响应流程图)

29

想了解Django---请求、响应的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于django请求响应流程图的相关问题,此外,我们还将为您介绍关于$Django调API的几种方式,djang

想了解Django--- 请求、响应的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于django请求响应流程图的相关问题,此外,我们还将为您介绍关于$ Django 调API的几种方式,django自定义错误响应、Django drf:视图层封装、ViewSetMixin、路由配置、解析器、响应器、Django 框架 day72------orm 增删改查、django 请求的生命周期、Django 框架篇(八): Django处理Ajax请求的新知识。

本文目录一览:

Django--- 请求、响应(django请求响应流程图)

Django--- 请求、响应(django请求响应流程图)

Django 的请求和响应

一、客户端向服务器的请求简介

二、响应对象构造

回到顶部

 

一、客户端向服务器的请求简介

  1.c-->s 的传参的 4 中途径 

    • 提取的 URL 的特定部分,如 / 天气 / 北京 / 2018,可以在服务器端的路由中用正则表达式截取;
    • 查询字符串(查询字符串),形如 key1 = value1&key2 = value2;
    • 请求体(主体)中发送的数据,比如表单数据,JSON,XML;
    • 在 HTTP 报文的头(报头)中。

  2. 传参途径的接受方式

    1. 通过 url 地址传递参数

      例如:在子路由 request_rout 中,urls 中设置  url(r''^weather/(?P<city>[a-z]+)/(?P<year>\d{4})/$'', views.weather),

def weather(request, year, city):
    print(''city=%s'' % city)
    print(''year=%s'' % year)
    return HttpResponse(''OK'')
request_rout/views

    2. 通过查询字符串传递参数  

# 演示从查询字符串中提取参数
# /query/?a=1&b=2&c=3
# flask: request.args
# dhango: request.GET -> QueryDict类的对象,类似于字典
def query_data(request):
    a = request.GET.get(''a'')
    b = request.GET.get(''b'')
    c = request.GET.get(''c'')

    c_list = request.GET.getlist(''c'') # list
    print(c_list)
    return HttpResponse("OK")
request_rout/views

    3. 通过请求体传递数据

      3.1post 表单提交数据

# 演示获取post表单提交的数据
# /form/
# flask: request.form
# dhango: request.POST -> QueryDict类的对象,类似于字典
def form_data(request):
    name = request.POST.get(''name'')
    age = request.POST.get(''age'')
    print(name)
    print(age)
    return HttpResponse(''OK'')
request_rout/views

      3.2json 数据

# 演示获取json数据
# /json/
# flask: request.json
# dhango: request.body -> QueryDict类的对象,类似于字典
def json_data(request):
    req_data = request.body  # 获取请求体原始数据 bytes

    # 将bytes转换成str
    json_str = req_data.decode()

    # 将json字符转为字典
    req_dict = json.loads(json_str)

    # 取出年龄和名字
    name = req_dict.get(''name'')
    age = req_dict.get(''age'')

    print(name)
    print(age)

    return HttpResponse(''OK'')
request_rout/views

    4. 通过请求头传递数据 (request.META)

def get_headers(request):
    print(request.META[''CONTENT_TYPE''])
    return HttpResponse(''OK'')
request_rout/views
CONTENT_LENGTH - 请求正文的长度(作为字符串)。
CONTENT_TYPE - 请求正文的MIME类型。
HTTP_ACCEPT - 响应的可接受内容类型。
HTTP_ACCEPT_ENCODING - 可接受的响应编码。
HTTP_ACCEPT_LANGUAGE - 响应的可接受语言。
HTTP_HOST - 客户端发送的HTTP主机头。
HTTP_REFERER - 引用页面,如果有的话。
HTTP_USER_AGENT - 客户端的用户代理字符串。
QUERY_STRING - 查询字符串,作为单个(未解析的)字符串。
REMOTE_ADDR - 客户端的IP地址。
REMOTE_HOST - 客户端的主机名。
REMOTE_USER - Web服务器验证的用户(如果有)。
REQUEST_METHOD- 一个字符串,如"GET""POST"
SERVER_NAME - 服务器的主机名。
SERVER_PORT - 服务器的端口(作为字符串)。
请求头常见值

  3.Django 中的 QueryDict 对象

    1.HttpRequest 对象的属性 GET,POST 都是的 QueryDict 类型的对象,QueryDict 类型的对象用来处理同一个键带有多个值的情况

  

   2. 得到 value 值的方法

     2.1 方法得到():根据键获取值

    如果一个键同时拥有多个值将获取最后一个值

    如果键不存在则返回无值,可以设置默认值进行后续处理

 dict.get(''键'',默认值) 可简写为 dict[''键'']

    2.2 方法的 GetList():根据键获取值,值以列表返回,可以获取指定键的所有值

    如果键不存在则返回空列表 [],可以设置默认值进行后续处理

 dict.getlist(''键'',默认值)

二、响应对象构造

  1. 返回 HttpResponse 类的对象或其子类的对象

    1.1 格式

      response = HttpResponse (''< 响应体>'', content_type=''< 响应数据类型 >'',  status=''< 响应状态码 >'')

                     res_http[''name''] = ''yang'' 

# 演示构造响应对象
# /get_response/
def get_response(request):
    res_http = HttpResponse("response_body", content_type=''text/html'',status=200)
    res_http[''name''] = ''yang''
    return res_http
代码

  2. 响应时返回 json 数据 

# 演示响应时返回json数据
# /get_json/
# flask: jsonify
# Dhango: JsonResponse(<dict>)
def get_json(request):
    res_dict = {
        "name" : "yang",
        "age" : 12
    }

    return JsonResponse(res_dict)
代码

  3. 响应时进行页面重定向

# 演示响应时进行页面重定向
# /redirect_test
# flask和django相同
# redirect(''url地址'')
def redirect_test(request):
    # 重定向首页
    req_url = reverse(''users:index'')
    print(req_url)
    return redirect(req_url)
代码

 

$ Django 调API的几种方式,django自定义错误响应

$ Django 调API的几种方式,django自定义错误响应

django自定义错误响应

  前提:settings.py

   #debug为true时要配置网站的allowed_hosts域名
# 简单就为"*"
DEBUG = False
ALLOWED_HOSTS = [''127.0.0.1'']
直接templates下书写404.htm,400.html,403.html,500.html
方式1
#第一步:总的urls.py 重写handler函数,(注意要加项目app名  要写在上面)
from django.conf.urls import url
from django.contrib import admin
from app01 import views
# handler404="app01.views.erro"
# handler400="app01.views.erro"
# handler403="app01.views.erro"
# handler500="app01.views.erro"

urlpatterns = [
    url(r''^admin/'', admin.site.urls),
    url(r''^download/'', views.Download),#下载
    url(r''^file/'', views.File.as_view()),#播放
    url(r''^tes/'', views.tes),#test
    url(r''^data/'', views.date),#test
]
#第二步:views.py写错误调的视图
from django.http import HttpResponseNotFound
def erro(request):
    return HttpResponseNotFound("NOT FOUND!")
方式2

API调用方式

下面是python中会用到的库。
urllib2
httplib2
pycurl
requests
urllib2

#request
import requests, json 
github_url = ” 
data = json.dumps({‘name’:’test’, ‘description’:’some test repo’}) 
r = requests.post(github_url, data, auth=(‘user’, ‘*‘)) 
print r.json 
#以上几种方式都可以调用API来执行动作,但requests这种方式代码最简洁,最清晰,建议采用。
#urllib2, urllib 
import urllib2, urllib 
github_url = ‘https://api.github.com/user/repos’ 
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() 
password_manager.add_password(None, github_url, ‘user’, ‘*‘) 
auth = urllib2.HTTPBasicAuthHandler(password_manager) # create an authentication handler 
opener = urllib2.build_opener(auth) # create an opener with the authentication handler 
urllib2.install_opener(opener) # install the opener… 
request = urllib2.Request(github_url, urllib.urlencode({‘name’:’Test repo’, ‘description’: ‘Some test repository’})) # Manual encoding required 
handler = urllib2.urlopen(request) 
print handler.read()
#httplib2
import urllib, httplib2 
github_url = ’ 
h = httplib2.Http(“.cache”) 
h.add_credentials(“user”, “**“, ” 
data = urllib.urlencode({“name”:”test”}) 
resp, content = h.request(github_url, “POST”, data) 
print content
#pycurl
import pycurl, json 
github_url = ” 
user_pwd = “user:*” 
data = json.dumps({“name”: “test_repo”, “description”: “Some test repo”}) 
c = pycurl.Curl() 
c.setopt(pycurl.URL, github_url) 
c.setopt(pycurl.USERPWD, user_pwd) 
c.setopt(pycurl.POST, 1) 
c.setopt(pycurl.POSTFIELDS, data) 
c.perform() 

 

Django drf:视图层封装、ViewSetMixin、路由配置、解析器、响应器

Django drf:视图层封装、ViewSetMixin、路由配置、解析器、响应器

一、视图层封装

二、ViewSetMixin

三、路由配置

四、解析器

五、响应器

 

一、视图层封装

  1.基本视图

    写一个出版社的增删改查resfull接口

    路由:

url(r''^publish/$'', views.PublishView.as_view()),
    url(r''^publish/(?P<pk>\d+)/$'', views.PublishDetailView.as_view()),

    视图:

class PublishSerializers(serializers.ModelSerializer):
    class Meta:
        model=models.Publish
        fields=''__all__''

class PublishView(APIView):

    def get(self, request):
        publish_list = models.Publish.objects.all()
        bs = PublishSerializers(publish_list, many=True)
        # 序列化数据

        return Response(bs.data)

    def post(self, request):
        # 添加一条数据
        print(request.data)

        bs=PublishSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return Response(bs.data)
        else:

            return Response(bs.errors)

class PublishDetailView(APIView):
    def get(self,request,pk):
        publish_obj=models.Publish.objects.filter(pk=pk).first()
        bs=PublishSerializers(publish_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        publish_obj = models.Publish.objects.filter(pk=pk).first()

        bs=PublishSerializers(data=request.data,instance=publish_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Publish.objects.filter(pk=pk).delete()

        return Response("")

  2.mixin类和generrice类编写视图

from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin
from rest_framework.generics import GenericAPIView
class PublishView(ListModelMixin,CreateModelMixin,GenericAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

class PublishDetailView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers
    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)

  3.使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
class PublishView(ListCreateAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

class PublishDetailView(RetrieveUpdateDestroyAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

  4.使用ModeiViewSet

    路由:

url(r''^publish/$'', views.PublishView.as_view({''get'':''list'',''post'':''create''})),
    url(r''^publish/(?P<pk>\d+)/$'', views.PublishView.as_view({''get'':''retrieve'',''put'':''update'',''delete'':''destroy''})),

    视图:

from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

 

二、ViewSetMixin

-ViewSetMixin
        # ViewSetMixin 写在前面,先找ViewSetMixin的as_view方法
        # 用了ViewSetMixin ,视图类中,不需要再写get,post,delete....这些函数了,函数名可以自定义
        # 而且这个视图类,可以响应多条路由
        
        -使用:
            -urls.py中
                url(r''^publishs/'', views.PublishView.as_view({''get'': ''aaa'',''post'':''ddd''})),
                url(r''^bbb/'', views.PublishView.as_view({''get'': ''bbb'',''post'':''ccc''})),
                
            -视图类中:
                class PublishView(ViewSetMixin,APIView):
                    def aaa(self,request):
                        return Response({''status'':100})
                    def bbb(self,request):
                        return Response({''bb'': "bbb"})

 

三、路由控制器

  1.自定义路由(原生方式)

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r''^books/$'', views.BookView.as_view()),
    url(r''^books/(?P<pk>\d+)$'', views.BookDetailView.as_view()),
]
class BookView(APIView):

    def get(self, request):
        book_list = models.Book.objects.all()
        bs = BookSerializers(book_list, many=True)
        return Response(bs.data)

    def post(self, request):
        # 添加一条数据
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return Response(bs.data)
        else:

            return Response(bs.errors)

class BookDetailView(APIView):
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()

        bs=BookSerializers(data=request.data,instance=book_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Book.objects.filter(pk=pk).delete()

        return Response(""

 

  2.半自动路由(视图类继承ModeViewSet)

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r''^publish/$'', views.PublishView.as_view({''get'':''list'',''post'':''create''})),
    url(r''^publish/(?P<pk>\d+)/$'', views.PublishView.as_view({''get'':''retrieve'',''put'':''update'',''delete'':''destroy''})),

]
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

 

  3.全自动路由(自动生成路由)

from django.conf.urls import url,include
from app01 import views
from rest_framework import routers
router=routers.DefaultRouter()
# 两个参数,一个是匹配的路由,一个是视图中写的CBV的类
router.register(''publish'',views.PublishView)
urlpatterns = [
    # http://127.0.0.1:8000/publish/format=json(渲染器通过这个判断,返回渲染的页面)
    # url(r''^publish/'', views.PublishView.as_view({''get'':''list'',''post'':''create''})),
    # http://127.0.0.1:8000/publish.json(渲染器通过这个判断,返回渲染的页面)
    # url(r''^publish\.(?P<format>\w+)$'', views.PublishView.as_view({''get'':''list'',''post'':''create''})),
    
    # 可以用 以下方式访问
    # 1 http://127.0.0.1:8000/publish/
    # 2 http://127.0.0.1:8000/publish.json
    # 3 http://127.0.0.1:8000/publish/3
    # 4 http://127.0.0.1:8000/publish/3.json   
    url(r'''',include(router.urls))
]
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers
# 小结:
-传统的url配置
   url(r''^books/$'', views.BookView.as_view()),
   url(r''^books/(?P<pk>\d+)$'', views.BookDetailView.as_view()),
  -半自动
    url(r''^publish/$'', views.PublishView.as_view({''get'':''list'',''post'':''create''})),
   url(r''^publish/(?P<pk>\d+)/$'', views.PublishView.as_view({''get'':''retrieve'',''put'':''update'',''delete'':''destroy''})),
  -全自动(了解)
   -能自动生成多条路由

 

四、解析器

  1.解析器的作用

    根据请求头content-type选择对应的解析器队请求体内容进行处理

    有appliction/json,x-www-form-urlencoded,form-data等格式

  2.全局使用解析器

    setting里

REST_FRAMEWORK = {
    ''DEFAULT_PARSER_CLASSES'':[
        ''rest_framework.parsers.JSONParser''
        ''rest_framework.parsers.FormParser''
        ''rest_framework.parsers.MultiPartParser''
    ]

}

    路由:

urlpatterns = [
    url(r''test/'', TestView.as_view()),
]

    视图函数:

from rest_framework.views import APIView
from rest_framework.response import Response

class TestView(APIView):
    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response(''POST请求,响应内容'')

    def put(self, request, *args, **kwargs):
        return Response(''PUT请求,响应内容'')

  3.局部使用解析器

a.仅处理请求头content-type为appliction/json请求体

from django.conf.urls import url, include
from web.views.s5_parser import TestView

urlpatterns = [
    url(r''test/'', TestView.as_view(), name=''test''),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser


class TestView(APIView):
    parser_classes = [JSONParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)

        return Response(''POST请求,响应内容'')

    def put(self, request, *args, **kwargs):
        return Response(''PUT请求,响应内容'')

b.仅处理请求头content-type为appliction/x-www-from-urlencoded的请求体

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r''test/'', TestView.as_view(), name=''test''),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser


class TestView(APIView):
    parser_classes = [FormParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)

        return Response(''POST请求,响应内容'')

    def put(self, request, *args, **kwargs):
        return Response(''PUT请求,响应内容'')

c.仅仅处理请求头content-type为multipart/form-data的请求体

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r''test/'', TestView.as_view(), name=''test''),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import MultiPartParser


class TestView(APIView):
    parser_classes = [MultiPartParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response(''POST请求,响应内容'')

    def put(self, request, *args, **kwargs):
        return Response(''PUT请求,响应内容'')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
    <input type="text" name="user" />
    <input type="file" name="img">

    <input type="submit" value="提交">

</form>
</body>
</html>

d.仅上传文件

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r''test/(?P<filename>[^/]+)'', TestView.as_view(), name=''test''),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser


class TestView(APIView):
    parser_classes = [FileUploadParser, ]

    def post(self, request, filename, *args, **kwargs):
        print(filename)
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response(''POST请求,响应内容'')

    def put(self, request, *args, **kwargs):
        return Response(''PUT请求,响应内容'')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
    <input type="text" name="user" />
    <input type="file" name="img">

    <input type="submit" value="提交">

</form>
</body>
</html>

e.同时多个Parser

当同时使用多个parser时,rest_framework会根据请求头content-type自动进行比对,并使用对应parser

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r''test/'', TestView.as_view(), name=''test''),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser


class TestView(APIView):
    parser_classes = [JSONParser, FormParser, MultiPartParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response(''POST请求,响应内容'')

    def put(self, request, *args, **kwargs):
        return Response(''PUT请求,响应内容'')

  4.源码分析

1 在调用request.data时,才进行解析,由此入手
    @property
    def data(self):
        if not _hasattr(self, ''_full_data''):
            self._load_data_and_files()
        return self._full_data
        
2 查看self._load_data_and_files()方法---->self._data, self._files = self._parse()

        def _parse(self):
            #用户请求头里content_type的值
            media_type = self.content_type

            #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
            #self里就有content_type,传入此函数
            parser = self.negotiator.select_parser(self, self.parsers)

3 查看self.negotiator.select_parser(self, self.parsers)
     def select_parser(self, request, parsers):
        #同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
        #每个解析器都有media_type = ''multipart/form-data''属性
        for parser in parsers:
            if media_type_matches(parser.media_type, request.content_type):
                return parser
        return None
    
4 最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)
1 Request实例化,parsers=self.get_parsers()
    Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
2 get_parsers方法,循环实例化出self.parser_classes中类对象
    def get_parsers(self):
        return [parser() for parser in self.parser_classes]            

3 self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
4 api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
        def __getattr__(self, attr):
            if attr not in self.defaults:
                raise AttributeError("Invalid API setting: ''%s''" % attr)

            try:
                #调用self.user_settings方法,返回一个字典,字典再取attr属性
                val = self.user_settings[attr]
            except KeyError:
                # Fall back to defaults
                val = self.defaults[attr]

            # Coerce import strings into classes
            if attr in self.import_strings:
                val = perform_import(val, attr)

            # Cache the result
            self._cached_attrs.add(attr)
            setattr(self, attr, val)
            return val
 5 user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
    @property
    def user_settings(self):
        if not hasattr(self, ''_user_settings''):
            self._user_settings = getattr(settings, ''REST_FRAMEWORK'', {})
        return self._user_settings

 

五、响应器

  1.作用

    根据用户请求url或用户可接受的类型,筛选出合适的渲染组件

    用户请求URL:

      http://127.0.0.1:8000/test/?format=json
           http://127.0.0.1:8000/test.json

  

  2.内置渲染器  

显示json格式:JSONRenderer

访问URL:

  • http://127.0.0.1:8000/test/?format=json
  • http://127.0.0.1:8000/test.json
  • http://127.0.0.1:8000/test/
     

默认显示格式:BrowsableAPIRenderer(可以修改它的html文件)

访问URL:

  • http://127.0.0.1:8000/test/?format=api
  • http://127.0.0.1:8000/test.api
  • http://127.0.0.1:8000/test/

 

表格方式:AdminRenderer

访问URL:

  • http://127.0.0.1:8000/test/?format=admin
  • http://127.0.0.1:8000/test.admin
  • http://127.0.0.1:8000/test/

 

form表单方式:HTMLFormRenderer

访问URL:

  • http://127.0.0.1:8000/test/?format=form
  • http://127.0.0.1:8000/test.form
  • http://127.0.0.1:8000/test/

  3.局部使用

from rest_framework.renderers import  HTMLFormRenderer,BrowsableAPIRenderer
class BookDetailView(APIView):
    renderer_classes = [HTMLFormRenderer,BrowsableAPIRenderer ]
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()

        bs=BookSerializers(data=request.data,instance=book_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Book.objects.filter(pk=pk).delete()

        return Response("")

 

  4.全局使用

    setting里配置:

REST_FRAMEWORK = {
    ''DEFAULT_RENDERER_CLASSES'':[''rest_framework.renderers.JSONRenderer'']
}

 

  5.自定义显示模板

from rest_framework.renderers import  TemplateHTMLRenderer
class BookDetailView(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data,template_name=''aa.html'')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{{ title }}
{{ publishDate }}
</body>
</html>

 

Django 框架 day72------orm 增删改查、django 请求的生命周期

Django 框架 day72------orm 增删改查、django 请求的生命周期

一、orm 介绍

  1.orm 的使用

    (1)tools--->Run manage.py Task

      makemigrations(记录数据库的修改记录)

      migrate(把数据同步到数据库)

    (2)python3 manage.py makemigrations

  2.orm 能做的事情与不能做的事情

    (1) 能创建数据表,新增和删除字段

    (2) 不能创建数据库

  3.orm 增加字段(注意:数据库迁移命令两条,后来增加的字段需要有默认值)

  4. 删除字段

    注释掉字段,执行数据库迁移的命令

  5. 修改字段

    直接修改字段,执行数据库迁移命令

  6.user 的增删改查 ------ 重点

    

1 单表查询所有用户:models.User.objects.all()
得到的是 queryset对象(当成列表),列表里面,一个一个的对象[user1,user2]
2 render(request, ''userlist.html'', {''user_list'': ret})
3 模板里: {% for user in user_list %}
#要循环的内容
{{user.name}}
{% endfor%}
4 get请求携带参数:
http://127.0.0.1:8000/deleteuser/?id=1
后台取值:request.GET.get(''id'')
request.GET[''id'']
5 orm删除记录 models.User.objects.filter(id=id).delete()
返回值:影响的行数
6 前台post提交的数据取值:name=request.POST.get(''name'')
7 orm保存:
两种方式:
1 user=models.User.objects.create(name=name,password=pwd,address=addr)
2 user=models.User(name=name,password=pwd,address=addr)
user.save()
8 orm查询单条数据:user=models.User.objects.filter(id=id).first()
9 orm的修改 models.User.objects.filter(id=id).update(name=name,password=pwd,address=addr)
  7.django的请求生命周期
    用户浏览器--->web服务器--->中间件--->url路由层--->视图层拿到数据--->模板层拿到一个模板,通过数据渲染到模板上--->原路返回

    

Django 框架篇(八): Django处理Ajax请求

Django 框架篇(八): Django处理Ajax请求

一. Ajax 简介:

AJAXAsynchronous Javascript And XML)翻译成中文就是异步的JavascriptXML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

 

详情请见: 前端之jQuery 中的Ajax交互方式

 

二. JSON字符串介绍:

定义:

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言 *
  • JSON 具有自我描述性,更易理解

 

javascript中  对象 转化成json字符串的方法: 

JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 

JSON.stringify({"name":"alex"})

javascript中  json字符串 转化成 js对象的方法: 

JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象 

JSON.parse(''{"name":"alex"}'');

 

三. Django处理Ajax的post请求:

正常的Django处理form表单中的post请求:

  因为django中中间件的保护机制, 需要对请求中的cookie和表单中的  "csrfmiddlewaretoken"  进行匹配,所以需要在页面中加上 {% csrf_token %} 标签来进行验证;

  而Ajax中的请求不是通过form表单进行发送的, 所以, 就需要想办法 获取到  "csrfmiddlewaretoken"  所对应的值, 一起发过去.

 

如何获取 "csrfmiddlewaretoken"  所对应的值

1. 通过jQuery的属性选择器获取:

  在这里还需要在html中 加入{% csrf_token %} 标签

复制代码
$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  data: {
    "username": "Q1mi",
    "password": 123456, "csrfmiddlewaretoken": $("[name = ''csrfmiddlewaretoken'']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中  }, success: function (data) { console.log(data); } })
复制代码

 

2. 通过获取cookie中的 ''csrftoken'' 在请求头中添加 "X-CSRFToken" 对应的键值对:

复制代码
$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  headers: {"X-CSRFToken": $.cookie(''csrftoken'')},  // 从Cookie取csrftoken,并设置到请求头中 data: {"username": "Q1mi", "password": 123456}, success: function (data) { console.log(data); } })
复制代码

 

3.  自己从新写一个获取cookie的js方法:

复制代码
function getCookie(name) {
    var cookieValue = null; if (document.cookie && document.cookie !== '''') { var cookies = document.cookie.split('';''); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + ''='')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie(''csrftoken''); // 上面是 自定义的 获取的 csrftoken ------------------------------------------------------------------------------------- // 下面是更改一下 ajax的初始化配置, 让每次的 ajax请求都提前添加 cookie的请求头 function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
复制代码

 

 

注意: 

  以上 方法都必须保证在页面加载的时候 cookie存在csrftoken的值.

  如果 html模板中没有包含 {% csrf_token %} 标签的话, django将不会设置 cookie;

  此时可以用  django.views.decorators.csrf  包中的 ensure_csrf_cookie 函数来进行装饰被访问的 视图函数  示例:

from django.views.decorators.csrf import ensure_csrf_cookie


@ensure_csrf_cookie
def login(request):
    pass

  官方有关csrf的解释文档

 

 

示例: 利用ajax上传文件:

复制代码
// 上传文件示例
$("#b3").click(function () {
  var formData = new FormData(); formData.append("csrfmiddlewaretoken", $("[name=''csrfmiddlewaretoken'']").val()); formData.append("f1", $("#f1")[0].files[0]); $.ajax({ url: "/upload/", type: "POST", processData: false, // 告诉jQuery不要去处理发送的数据 contentType: false, // 告诉jQuery不要去设置Content-Type请求头  data: formData, success:function (data) { console.log(data) } }) })
复制代码

 

关于Django--- 请求、响应django请求响应流程图的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于$ Django 调API的几种方式,django自定义错误响应、Django drf:视图层封装、ViewSetMixin、路由配置、解析器、响应器、Django 框架 day72------orm 增删改查、django 请求的生命周期、Django 框架篇(八): Django处理Ajax请求的相关信息,请在本站寻找。

本文标签: