欢迎来访我的博客。

Django Rest Framework学习总结-2:Requests和Responses

Django 小张哥哥 721浏览 24评论

从本文开始,我们开始进入到REST framework比较核心的部分。我们首先介绍一下组成框架的几个重要的组成部分。


Request对象

REST framework引入了一个Request对象,它是继承自常规的HttpRequest,提供了更加灵活的request解析。Request对象最核心的功能是request.data属性,这个属性和request.POST很像,但是对于开发Web API,它的用处更大。

request.POST  # 只处理表达数据。  只对POST方法有用。
request.data  # 处理任意数据。  对POST, PUT以及PATCH方法都有用。

Response对象

REST framework也引入了一个Response对象,它是TemplateResponse的一种。它携带未渲染的数据内容,并通过内容协商(content negotiation)来决定返回给客户端的内容的类型是什么。

return Response(data)  # Renders to content type as requested by the client.

Status codes

使用数字形式的HTTP状态码不容易让人理解,而且当得到一个错误的状态码时,我们也不容易注意到。REST framework通过定义的一些常量清晰明了的定义了每个状态码,比如status模块中HTTP_400_REQUEST。使用这种方式比使用数字形式的状态码要容易理解多了。

API视图的封装

REST framework提供了两种方式来写API视图。

  1. 对于基于函数的视图(function based views),我们可以使用@api_view装饰器。

  2. 对于基于类的视图(class-based views),我们可以使用APIView类。

这些封装提供了一些实用的功能。比如可以确保在我们的视图函数中接受到Request对象实例,并且添加context到Response对象实例中。
这些封装也提供其它一些行为,比如:在恰当的时候会返回205 Method Not Allowed的Response;当通过request.data获取的数据中含有错误格式的信息时,会处理任何的ParseError的异常信息。

使用组件编写API视图

至此,我们使用以上的这些组件,写一些视图函数。
我们现在不需要views.py文件中的JSONResponse类了。把这些内容删掉,重构一下我们的视图函数。

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Snippet
from .serializers import SnippetSerializer


@api_view(['GET', 'POST'])def snippet_list(request):
    """
    列出所有的snippet,或者创建一个新的snippet
    :param request:
    :return:
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)
    
    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(status=status.HTTP_201_CREATED)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

上面这个视图函数相比上一篇文章的例子,代码更加简介易懂了。而且代码跟之前的Django Form中的也非常相似。在上面代码中,我们还使用了框架定义的状态码,使代码更加清楚明了。

下面是views.py文件中,对于单个snippet实例的视图函数:

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk, format=None):
    """
    Retrieve, update or delete a code snippet.
    :param request:
    :return: HttpResponse or JsonResponse
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data, status=status.HTTP_200_OK)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return SnippetSerializer(serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

上面的这个视图和上次的常规的Django视图函数很相像。
在上面的视图函数中,request.data可以处理传进来的json类型的request。当然,它也可以处理其它的类型。
与此类似,我们返回的response对象中也有data数据,REST framework可以将response对象为我们转成正确的content type。


URLs中添加可选的format后缀

现在,我们的response对象并不是固定的某个content type。我们可以在我们的API后加上format后缀,这样我们的API就可以使用给定的format了。这样的化,我们的API就可以处理类似http://example.com/api/items/4.json 了。
我可以在我们的视图函数中添加format关键字。

def snippet_list(request, format=None)
def snippet_detail(request, pk, format=None)

然后,我们可以更新一下snippets/urls.py文件,将rest_framework.urlpatterns中的format_suffix_pattern添加到URLs中。

from django.url import path
from rest_framework.urlspatterns import formate_suffix_patterns
from snippets import views

urlpatterns = [
    path('snippets/', views.snippet_list),
    path('snippets/<int:pk>', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)


在上面的代码中,我们不需要手动添加另外的path路径,直接调用format_suffix_patterns方法就行了。


测试API

现在,我们在命令行中继续测试我们的API。
测试发现,返回的信息和上节测试中的表现相似。
获取所有的snippets的列表

HTTP/1.1 200 OK
Allow: OPTIONS, POST, GET
Content-Length: 211
Content-Type: application/json
Date: Mon, 15 Jul 2019 10:59:48 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
[
    {
        "code": "foo = \"bar\"\n",        
        "id": 1,        
        "language": "python",        
        "linenos": false,        
        "style": "friendly",        
        "title": ""
    },    
    {
        "code": "print(\"hello, world\")\n",        
        "id": 2,        
        "language": "python",        
        "linenos": false,        
        "style": "friendly",        
        "title": ""
    }
]

我们可以通过format参数控制response返回的格式,有两种方法:
一种是在请求时使用Accept头:

http http://127.0.0.1:8000/snippets/ Accept:application/json  # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html         # Request HTML

另一种在请求时候添加格式后缀:

http http://127.0.0.1:8000/snippets.json  # JSON suffix
http http://127.0.0.1:8000/snippets.api   # Browsable API suffix

与此类似,我们也可以控制我们发出的request的格式。方法是添加Content-Type头。

# POST using form data
http --form POST http://127.0.0.1:8000/snippets/ code="print(123456)"
HTTP/1.1 201 Created
Allow: OPTIONS, POST, GET
Content-Length: 97
Content-Type: application/json
Date: Mon, 15 Jul 2019 11:07:14 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
    "code": "print(123456)",    
    "id": 4,    
    "language": "python",    
    "linenos": false,    
    "style": "friendly",    
    "title": ""
}
# POST using JSON
http --json POST http://127.0.0.1:8000/snippets/ code="print('abcdef')"
HTTP/1.1 201 Created
Allow: OPTIONS, POST, GET
Content-Length: 99
Content-Type: application/json
Date: Mon, 15 Jul 2019 11:08:53 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
    "code": "print('abcdef')",    
    "id": 4,    
    "language": "python",    
    "linenos": false,    
    "style": "friendly",    
    "title": ""
}

在上面的请求中,如果我们添加--debug参数,可以看到在request的头部有request类型:

http --json POST http://127.0.0.1:8000/snippets/ code="print('abcdef')" --debug
HTTPie 1.0.2
Requests 2.22.0
Pygments 2.4.2
Python 3.6.0 (default, Jan 23 2017, 20:01:14) [MSC v.1900 64 bit (AMD64)]c:\python36\python.exe
Windows 10<Environment {
    "colors": 256,    
    "config": {
        "__meta__": {
            "about": "HTTPie configuration file",            
            "help": "https://httpie.org/doc#config",            
            "httpie": "1.0.2"
        },        
        "default_options": "[]"
    },    
    "config_dir": "C:\\Users\\zhang\\AppData\\Roaming\\\\httpie",    
    "is_windows": true,    
    "stderr": "<colorama.ansitowin32.StreamWrapper object at 0x000001F878B54470>",    
    "stderr_isatty": true,    
    "stdin": "<_io.TextIOWrapper name='<stdin>' mode='r' encoding='utf-8'>",    
    "stdin_encoding": "utf-8",    
    "stdin_isatty": true,    
    "stdout": "<colorama.ansitowin32.StreamWrapper object at 0x000001F878B54320>",    
    "stdout_encoding": "utf-8",    "stdout_isatty": true}
>>>> requests.request(**{
    "allow_redirects": false,    
    "auth": "None",    
    "cert": "None",    
    "data": "{\"code\": \"print('abcdef')\"}",    
    "files": {},    
    "headers": {
        "Accept": "application/json, */*",        
        "Content-Type": "application/json",        
        "User-Agent": "HTTPie/1.0.2"
    },    
    "method": "post",    
    "params": {},    
    "proxies": {},    
    "stream": true,    
    "timeout": 30,    
    "url": "http://127.0.0.1:8000/snippets/",    
    "verify": true})
    
HTTP/1.1 201 Created
Allow: OPTIONS, POST, GET
Content-Length: 99
Content-Type: application/json
Date: Mon, 15 Jul 2019 11:10:33 GMT
Server: WSGIServer/0.2 CPython/3.6.0
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
    "code": "print('abcdef')",    
    "id": 6,    
    "language": "python",    
    "linenos": false,    
    "style": "friendly",    
    "title": ""
}

现在我们可以在浏览器中访问 http://127.0.0.1:8000/snippets/来查看API。

由于API通过客户端的要求来选择发送的内容类型(content-type)。在默认情况下,当我们使用浏览器访问时,返回的是HTML格式。
现在有了一个可以使用浏览器访问的可视化的API,我们的开发就变得更加简单轻松了。而且它也可以让其它想使用你的API的开发人员工作更加简便。

另外,我们还可以通过下面的链接了解更多关于可视化的API的功能,以及如何去客制化它。

了解更多关于API的可视化



本文中的源码可以在Github上查看。点我查看本文源码


转载请注明:禅思 » Django Rest Framework学习总结-2:Requests和Responses?

喜欢 (2) or 分享 (0)

我的个人微信公众号,欢迎关注

扫码或搜索:Python后端开发Django

Python后端开发Django

微信公众号 扫一扫关注

结交朋友、一起学习,一起进步。

科波之主

QQ号 386046154 立即加入

添加微信,进行技术交流

专注技术交流, 一同成长进步

我的微信号

如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(24)个小伙伴在吐槽
    1. Django Rest Framework学习总结-2:Requests和Responses | 禅思 http://situspokersinar.co
      company website 2019-12-24 12:10:08 回复
      • This post will assist the internet viedwers forr setting up new web site or eeven a weblpg from staft to end.
        Wisata Alam 2020-01-16 04:16:06 回复
        • If you are going for best contents like me, only pay a visit tuis website every day since it provides feature contents, thanks
          sepakbola dunia 2020-01-23 16:53:56 回复
          • Django Rest Framework学习总结-2:Requests和Responses | 禅思 http://live.adtrackir1.co.uk/pub/inbound_email/track/click.php?email=sebastian.mille@mjvibe.com&url=https://www.hongkongpool.io/
            Keluaran HK 2020-01-30 08:28:21 回复
            • I tjink the admin of this website is actually working had for his web page, because here every stuff is quuality based data.
              berita unik 2020-01-30 10:50:37 回复
              • It's actually a great and ueful piece of information. I'm happy that you shared this useful inforation with us. Please keep us informed like this. Thank you for sharing.
                info Seputar wisata 2020-02-14 14:42:34 回复
                • Django Rest Framework学习总结-2:Requests和Responses | 禅思 http://rw.digitalairstrike.com/click.php?id=100587&site=7&page=http://18.182.187.26/
                  Togel Online 2020-03-25 19:24:41 回复
                  • http://bio-catalyst.com/ - generic cleocin keflex generic buy keftab order keflex
                    Jamesfer 2021-02-17 05:55:17 回复
                    • show cialis working cialis vs viagra buy viagra cialis http://cialisirt.com/ cialis money order nose congested when taking cialis lowest cialis prices
                      Kennethamigh 2021-02-18 03:08:45 回复
                      • how to get cialis samples canadien cialis viagra or cialis https://edplsgeneric.com/ herbal replacement for viagra/cialis/levitra... cialis or viagra cialis vidalista
                        Kennethamigh 2021-02-18 18:45:17 回复
                        • generic cialis at walmart cialis vs levitra cialis lowest price https://edplsgeneric.com/ cialis coupons printable generic cialis no doctor's prescription where to bay cialis (tadalafil) pills 80mg
                          Kennethamigh 2021-02-19 10:44:29 回复
                          • tadalafil vs cialis cialis maximum dosage how long does 20mg cialis keep in system http://cialisirt.com/ cialis reps liquid cialis interactions for cialis
                            Kennethamigh 2021-02-21 09:54:03 回复
                            • take cialis with or without food cialis money order tadalafil vs cialis http://cialisirt.com/ canada price on cialis cialis pills fastest delivery of cialis buying online
                              Kennethamigh 2021-02-22 02:29:02 回复
                              • how long does 20mg cialis keep in system viagra vs cialis generic cialis no doctor's prescription https://edplsgeneric.com/ 5 mg cialis coupon printable cialis vs viagra effectiveness cialis canada
                                Kennethamigh 2021-02-23 12:46:35 回复
                                • real cialis without a doctor prescription cialis coupon code 5 mg cialis coupon printable https://edplsgeneric.com/ generic cialis bitcoin cialis going generic in 2019 in us п»їcialis
                                  Kennethamigh 2021-02-24 05:52:43 回复
                                  • cialis for peyronie cialis 30 day trial voucher п»їcialis https://edplsgeneric.com/ generic cialis available cialis lowest price 20mg coupons for cialis
                                    Kennethamigh 2021-02-24 23:01:17 回复
                                    • cialis 100 mg lowest price online cialis canadian viagra cialis https://edplsgeneric.com/ cialis at a discount price cialis samples request hard erections cialis
                                      Kennethamigh 2021-02-25 15:59:49 回复
                                      • is cialis generic available lowest cialis prices switching from tamsulosin to cialis http://cialisirt.com/ otc cialis liquid cialis source reviews cialis or viagra
                                        Kennethamigh 2021-02-26 09:42:12 回复
                                        • cialis erection penis viagra vs cialis vs levitra safe alternatives to viagra and cialis http://cialisirt.com/ liquid cialis cialis online pharmacy generic cialis
                                          Kennethamigh 2021-02-26 22:21:02 回复
                                          • cialis maximum dosage cialis before and after cialis coupon code http://cialisirt.com/ real cialis without a doctor's prescription buy viagra cialis low cost cialis
                                            Kennethamigh 2021-02-27 10:17:13 回复
                                            • cialis ingredient real cialis online with paypal cialis vs viagra http://cialisirt.com/ how to take cialis buy cialis online cialis price
                                              Kennethamigh 2021-02-27 22:07:15 回复
                                              • side effects of cialis price of cialis switching from tamsulosin to cialis http://cialisirt.com/ buy cialis online cialis without a doctor's prescription generic cialis coming out
                                                Kennethamigh 2021-03-01 08:31:29 回复
                                                • generic cialis without prescription nose congested when taking cialis cost of cialis http://cialisirt.com/ cialis online cialis samples request how long does 20mg cialis keep in system
                                                  Kennethamigh 2021-03-02 08:13:28 回复
                                                  • generic tadalafil 40 mg tadalafil tablets tadalafil pills 20mg
                                                    Wesleyviord 2021-03-05 22:49:06 回复