亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Python > 正文

Python的Django REST框架中的序列化及請求和返回

2020-01-04 17:33:28
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Python的Django REST框架中的序列化及請求和返回,使用Django REST來實現RESTful web service非常方便和強大,需要的朋友可以參考下
 

序列化Serialization
1. 設置一個新的環境

在我們開始之前, 我們首先使用virtualenv要創建一個新的虛擬環境,以使我們的配置和我們的其他項目配置徹底分開。

$mkdir ~/env$virtualenv ~/env/tutorial$source ~/env/tutorial/bin/avtivate

現在我們處在一個虛擬的環境中,開始安裝我們的依賴包

$pip install django$pip install djangorestframework$pip install pygments  ////使用這個包,做代碼高亮顯示

需要退出虛擬環境時,運行deactivate。更多信息,irtualenv document

2. 開始

環境準備好只好,我們開始創建我們的項目

$ cd ~$ django-admin.py startproject tutorial$ cd tutorial

項目創建好后,我們再創建一個簡單的app

$python manage.py startapp snippets

我們使用sqlite3來運行我們的項目tutorial,編輯tutorial/settings.py, 將數據庫的默認引擎engine改為sqlite3, 數據庫的名字NAME改為tmp.db

DATABASES = {  'default': {    'ENGINE': 'django.db.backends.sqlite3',    'NAME': 'tmp.db',    'USER': '',    'PASSWORD': '',    'HOST': '',    'PORT': '',  }}

同時更改settings.py文件中的INSTALLD_APPS,添加我們的APP snippets和rest_framework

INSTALLED_APPS = (  ...  'rest_framework',  'snippets',)

在tutorial/urls.py中,將snippets app的url包含進來

urlpatterns = patterns('',  url(r'^', include('snippets.urls')),)

3. 創建Model
這里我們創建一個簡單的nippets model,目的是用來存儲代碼片段。

from django.db import modelsfrom pygments.lexers import get_all_lexersfrom pygments.styles import get_all_stylesLEXERS = [item for item in get_all_lexers() if item[1]]LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])STYLE_CHOICES = sorted((item, item) for item in get_all_styles())class Snippet(models.Model):  created = models.DateTimeField(auto_now_add=True)  code = models.TextField()  linenos = models.BooleanField(default=False)  language = models.CharField(choices=LANGUAGE_CHOICES,                default='python',                max_length=100)  style = models.CharField(choices=STYLE_CHOICES,               default='friendly',               max_length=100)  class Meta:    ordering = ('created',)

 

完成model時,記得sync下數據庫

python manage.py syncdb

 

4. 創建序列化類

我們要使用我們的web api,要做的第一件事就是序列化和反序列化, 以便snippets實例能轉換為可表述的內容,例如json. 我們聲明一個可有效工作的串行器serializer。在snippets目錄下面,該串行器與django 的表單形式很類似。創建一個serializers.py ,并將下面內容拷貝到文件中。

from django.forms import widgetsfrom rest_framework import serializersfrom snippets.models import Snippetclass SnippetSerializer(serializers.Serializer):  pk = serializers.Field() # Note: `Field` is an untyped read-only field.                 max_length=100)  code = serializers.CharField(widget=widgets.Textarea,                 max_length=100000)  linenos = serializers.BooleanField(required=False)  language = serializers.ChoiceField(choices=models.LANGUAGE_CHOICES,                    default='python')  style = serializers.ChoiceField(choices=models.STYLE_CHOICES,                  default='friendly')  def restore_object(self, attrs, instance=None):    """    Create or update a new snippet instance.    """    if instance:      # Update existing instance      instance.title = attrs['title']      instance.code = attrs['code']      instance.linenos = attrs['linenos']      instance.language = attrs['language']      instance.style = attrs['style']      return instance    # Create new instance    return Snippet(**attrs)

該序列化類的前面部分,定義了要序列化和反序列化的類型,restore_object 方法定義了如何通過反序列化數據,生成正確的對象實例。

我們也可以使用ModelSerializer來快速生成,后面我們將節省如何使用它。
5. 使用 Serializers

在我們使用我們定義的SnippetsSerializers之前,我們先熟悉下Snippets.

 $python manage.py shell

進入shell終端后,輸入以下代碼:

from snippets.models import Snippetfrom snippets.serializers import SnippetSerializerfrom rest_framework.renderers import JSONRendererfrom rest_framework.parsers import JSONParsersnippet = Snippet(code='print "hello, world"/n')snippet.save()

 

我們現在獲得了一個Snippets的實例,現在我們對他進行以下序列化

serializer = SnippetSerializer(snippet)serializer.data# {'pk': 1, 'title': u'', 'code': u'print "hello, world"/n', 'linenos': False, 'language': u'python', 'style': u'friendly'}

這時,我們將該實例轉成了python原生的數據類型。下面我們將該數據轉換成json格式,以完成序列化:

content = JSONRenderer().render(serializer.data)content# '{"pk": 1, "title": "", "code": "print //"hello, world//"//n", "linenos": false, "language": "python", "style": "friendly"}'

反序列化也很簡單,首先我們要將一個輸入流(content),轉換成python的原生數據類型

import StringIOstream = StringIO.StringIO(content)data = JSONParser().parse(stream)

然后我們將該原生數據類型,轉換成對象實例

serializer = SnippetSerializer(data=data)serializer.is_valid()# Trueserializer.object# <Snippet: Snippet object>

注意這些API和django表單的相似處。這些相似點, 在我們講述在view中使用serializers時將更加明顯。
6. 使用 ModelSerializers

SnippetSerializer使用了許多和Snippet中相同的代碼。如果我們能把這部分代碼去掉,看上去將更佳簡潔。

類似與django提供Form類和ModelForm類,Rest Framework也包含了Serializer 類和 ModelSerializer類。

打開snippets/serializers.py ,修改SnippetSerializer類:

class SnippetSerializer(serializers.ModelSerializer):  class Meta:    model = Snippet    fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

7. 通過Serializer編寫Django View

讓我們來看一下,如何通過我們創建的serializer類編寫django view。這里我們不使用rest framework的其他特性,僅編寫正常的django view。

我們創建一個HttpResponse 子類,這樣我們可以將我們返回的任何數據轉換成json。

在snippet/views.py中添加以下內容:

from django.http import HttpResponsefrom django.views.decorators.csrf import csrf_exemptfrom rest_framework.renderers import JSONRendererfrom rest_framework.parsers import JSONParserfrom snippets.models import Snippetfrom snippets.serializers import SnippetSerializerclass JSONResponse(HttpResponse):  """  An HttpResponse that renders it's content into JSON.  """  def __init__(self, data, **kwargs):    content = JSONRenderer().render(data)    kwargs['content_type'] = 'application/json'    super(JSONResponse, self).__init__(content, **kwargs)

我們API的目的是,可以通過view來列舉全部的Snippet的內容,或者創建一個新的snippet

@csrf_exemptdef snippet_list(request):  """  List all code snippets, or create a new snippet.  """  if request.method == 'GET':    snippets = Snippet.objects.all()    serializer = SnippetSerializer(snippets)    return JSONResponse(serializer.data)  elif request.method == 'POST':    data = JSONParser().parse(request)    serializer = SnippetSerializer(data=data)    if serializer.is_valid():      serializer.save()      return JSONResponse(serializer.data, status=201)    else:      return JSONResponse(serializer.errors, status=400)

注意,因為我們要通過client向該view post一個請求,所以我們要將該view 標注為csrf_exempt, 以說明不是一個CSRF事件。
Note that because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as csrf_exempt. This isn't something that you'd normally want to do, and REST framework views actually use more sensible behavior than this, but it'll do for our purposes right now.
我們也需要一個view來操作一個單獨的Snippet,以便能更新/刪除該對象。

@csrf_exemptdef snippet_detail(request, pk):  """  Retrieve, update or delete a code snippet.  """  try:    snippet = Snippet.objects.get(pk=pk)  except Snippet.DoesNotExist:    return HttpResponse(status=404)  if request.method == 'GET':    serializer = SnippetSerializer(snippet)    return JSONResponse(serializer.data)  elif request.method == 'PUT':    data = JSONParser().parse(request)    serializer = SnippetSerializer(snippet, data=data)    if serializer.is_valid():      serializer.save()      return JSONResponse(serializer.data)    else:      return JSONResponse(serializer.errors, status=400)  elif request.method == 'DELETE':    snippet.delete()    return HttpResponse(status=204)

 

將views.py保存,在Snippets目錄下面創建urls.py,添加以下內容:

urlpatterns = patterns('snippets.views',  url(r'^snippets/$', 'snippet_list'),  url(r'^snippets/(?P<pk>[0-9]+)/$', 'snippet_detail'),)

注意我們有些邊緣事件沒有處理,服務器可能會拋出500異常。
8. 測試

現在我們啟動server來測試我們的Snippet。

在python mange.py shell終端下執行(如果前面進入還沒有退出)

 >>quit()

 

執行下面的命令, 運行我們的server:

 python manage.py runserverValidating models...0 errors foundDjango version 1.4.3, using settings 'tutorial.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.

新開一個terminal來測試我們的server

序列化:

url http://127.0.0.1:8000/snippets/[{"id": 1, "title": "", "code": "print /"hello, world/"/n", "linenos": false, "language": "python", "style": "friendly"}] url http://127.0.0.1:8000/snippets/1/{"id": 1, "title": "", "code": "print /"hello, world/"/n", "linenos": false, "language": "python", "style": "friendly"}

 


Request and Response
1. Request Object  ——Request對象

rest framework 引入了一個繼承自HttpRequest的Request對象,該對象提供了對請求的更靈活解析。request對象的核心部分是request.data屬性,類似于request.post, 但在使用WEB API時,request.data更有效。

(1)request.POST  # Only handles form data.  Only works for 'POST' method.
(2)request.DATA  # Handles arbitrary data.  Works any HTTP request with content.
2. Response Object ——Response對象
rest framework引入了一個Response 對象,它繼承自TemplateResponse對象。它獲得未渲染的內容并通過內容協商content negotiation 來決定正確的content type返回給client。

return Response(data)  # Renders to content type as requested by the client.
3. Status Codes
在views當中使用數字化的HTTP狀態碼,會使你的代碼不宜閱讀,且不容易發現代碼中的錯誤。rest framework為每個狀態碼提供了更明確的標識。例如HTTP_400_BAD_REQUEST。相比于使用數字,在整個views中使用這類標識符將更好。
4. 封裝API views

在編寫API views時,REST Framework提供了兩種wrappers:

1). @api_viwe 裝飾器 ——函數級別

2). APIView 類——類級別

這兩種封裝器提供了許多功能,例如,確保在view當中能夠接收到Request實例;往Response中增加內容以便內容協商content negotiation 機制能夠執行。

封裝器也提供一些行為,例如在適當的時候返回405 Methord Not Allowed響應;在訪問多類型的輸入request.DATA時,處理任何的ParseError異常。
5. 匯總

我們開始用這些新的組件來寫一些views。

我們不在需要JESONResponse 類(在前一篇中創建),將它刪除。刪除后我們開始稍微重構下我們的view

from rest_framework import statusfrom rest_framework.decorators import api_viewfrom rest_framework.response import Responsefrom snippets.models import Snippetfrom snippets.serializers import SnippetSerializer@api_view(['GET', 'POST'])def snippet_list(request):  """  List all snippets, or create a new snippet.  """  if request.method == 'GET':    snippets = Snippet.objects.all()    serializer = SnippetSerializer(snippets)    return Response(serializer.data)  elif request.method == 'POST':    serializer = SnippetSerializer(data=request.DATA)    if serializer.is_valid():      serializer.save()      return Response(serializer.data, status=status.HTTP_201_CREATED)    else:      return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

上面的代碼是對我們之前代碼的改進??瓷先ジ啙崳哺愃朴赿jango的forms api形式。我們也采用了狀態碼,使返回值更加明確。
下面是對單個snippet操作的view更新:

@api_view(['GET', 'PUT', 'DELETE'])def snippet_detail(request, pk):  """  Retrieve, update or delete a snippet instance.  """         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)  elif request.method == 'PUT':    serializer = SnippetSerializer(snippet, data=request.DATA)    if serializer.is_valid():      serializer.save()      return Response(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)

注意,我們并沒有明確的要求requests或者responses給出content type。request.DATA可以處理輸入的json請求,也可以輸入yaml和其他格式。類似的在response返回數據時,REST Framework返回正確的content type給client。

6. 給URLs增加可選的格式后綴

利用在response時不需要指定content type這一事實,我們在API端增加格式的后綴。使用格式后綴,可以明確的指出使用某種格式,意味著我們的API可以處理類似http://example.com/api/items/4.json.的URL。

增加format參數在views中,如:

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

現在稍微改動urls.py文件,在現有的URLs中添加一個格式后綴pattterns (format_suffix_patterns):

from django.conf.urls import patterns, urlfrom rest_framework.urlpatterns import format_suffix_patternsurlpatterns = patterns('snippets.views',  url(r'^snippets/$', 'snippet_list'),  url(r'^snippets/(?P<pk>[0-9]+)$', 'snippet_detail'),)urlpatterns = format_suffix_patterns(urlpatterns)

這些額外的url patterns并不是必須的。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久久久久免费精品| 国产精品小说在线| 亚洲欧美在线免费| 日韩在线小视频| 麻豆国产va免费精品高清在线| 国产精品盗摄久久久| 亚洲精品国精品久久99热| 久久好看免费视频| 亚洲欧美日韩视频一区| 亚洲性生活视频在线观看| 国产精品白丝jk喷水视频一区| 欧美性色xo影院| 亚洲日本aⅴ片在线观看香蕉| 久久精品福利视频| 久久久久久成人| 色黄久久久久久| 欧美激情国内偷拍| 国产精品视频yy9099| 日韩av在线导航| 青青久久av北条麻妃黑人| 亚洲视频999| 亚洲一区二区三区视频| 亚洲一区二区三区在线视频| 久久久91精品| 影音先锋欧美在线资源| 亚洲国产女人aaa毛片在线| 国产精品第3页| 91国产精品电影| 日韩欧美精品网站| 国内精品模特av私拍在线观看| 久久精品在线视频| 青青青国产精品一区二区| 日本欧美国产在线| 日韩精品高清在线| 北条麻妃99精品青青久久| 亚洲乱码国产乱码精品精| 91精品国产91久久久久久最新| 欧美孕妇毛茸茸xxxx| 亚洲国产女人aaa毛片在线| 91免费在线视频网站| 久久久久久久久久亚洲| 精品久久久久人成| 国产精品吊钟奶在线| 久久久久国产精品免费| 岛国av一区二区在线在线观看| 日韩欧美在线免费观看| 成人日韩在线电影| 亚洲天堂av女优| 日韩中文字幕精品| 久久成人精品一区二区三区| 欧美插天视频在线播放| 久久久之久亚州精品露出| 日韩av在线免播放器| 日韩av免费看| 亚洲国产精品电影在线观看| 国产精品自产拍高潮在线观看| 精品成人久久av| 日韩激情片免费| 姬川优奈aav一区二区| 98视频在线噜噜噜国产| 久久精品国产亚洲一区二区| 久久精品人人爽| 国产91色在线播放| 国产精品视频不卡| 欧美午夜女人视频在线| 成人午夜黄色影院| 亚洲男人天堂2024| 日韩精品福利网站| 在线观看视频99| 日韩中文字幕不卡视频| 欧美限制级电影在线观看| 国产成人综合一区二区三区| 精品女厕一区二区三区| 久久久噜久噜久久综合| 欧美日韩在线视频一区| 亚洲伦理中文字幕| 久久久女女女女999久久| 色综合五月天导航| 一区二区三区 在线观看视| 国产精品高潮呻吟久久av无限| 夜夜嗨av一区二区三区四区| 精品免费在线观看| 国产成人亚洲综合| 欧美成人久久久| 91sa在线看| 97精品视频在线播放| 久久久国产精品免费| 国产精品免费久久久久影院| 国产一区二区三区在线免费观看| 久久免费视频这里只有精品| 欧美成人免费va影院高清| 欧美视频一二三| 97久久精品国产| 亚洲综合社区网| 欧美福利视频在线观看| 韩国精品久久久999| 91理论片午午论夜理片久久| 国产成人精品久久久| 成人免费视频网址| 日韩精品视频在线免费观看| 国产99久久精品一区二区| 精品国产视频在线| 国产综合在线看| 精品国产区一区二区三区在线观看| 国产精品自产拍高潮在线观看| 成人黄色短视频在线观看| 欧美激情一区二区三区久久久| 精品亚洲va在线va天堂资源站| 国产精品啪视频| 精品久久久国产| 久久精品色欧美aⅴ一区二区| 国产精品爱啪在线线免费观看| 亚洲区免费影片| 岛国av一区二区三区| 国产成人精品久久| 精品中文字幕在线观看| 日韩电影免费在线观看| 成人免费观看网址| 欧美日韩中文在线| 亚洲精品综合久久中文字幕| 91九色在线视频| 精品久久久久久中文字幕大豆网| 中文国产成人精品久久一| 欧美成人高清视频| 日韩福利在线播放| 亚洲第一视频在线观看| 欧美又大粗又爽又黄大片视频| 国产一区私人高清影院| 欧美多人爱爱视频网站| 欧美精品激情视频| 97免费视频在线播放| 色综合天天综合网国产成人网| 亚洲第一二三四五区| 国产欧美在线视频| 亚洲高清免费观看高清完整版| 国产一区二区三区在线看| 日韩电影中文字幕在线| 欧美色视频日本版| 免费97视频在线精品国自产拍| 国产成人欧美在线观看| 亚洲精品自拍第一页| 国产精品亚洲激情| 美女视频黄免费的亚洲男人天堂| 国产精品ⅴa在线观看h| 亚洲欧美日韩天堂| 97视频国产在线| 亚洲综合色av| 911国产网站尤物在线观看| 成人妇女免费播放久久久| 欧美成人精品在线视频| 亚洲高清av在线| 高清欧美性猛交xxxx黑人猛交| 亚洲无亚洲人成网站77777| 欧美丝袜一区二区三区| 中文字幕日韩专区| 久久精品人人爽| 91精品国产电影| 欧美怡红院视频一区二区三区| 日韩美女激情视频| 久久久久这里只有精品| 影音先锋欧美精品| 国内精品模特av私拍在线观看| 亚洲精品视频免费在线观看| 欧美激情一区二区三区成人|