摘要:我們可以通過聲明與表單非常相似的序列化器來做到這一點。具有的一個不錯的屬性是可以通過打印其表示來檢查序列化器實例中的所有字段。
建議直接去http://www.chenxm.cc/post/289... 該網址閱讀,本文內容之后于該網頁
建立環境
在我們做任何事情之前,我們將使用virtualenv創建一個新的虛擬環境。這將確保我們的包配置與我們正在開展的任何其他項目保持良好的隔離。
</>復制代碼
virtualenv
envsource env/bin/activate
現在我們在一個virtualenv環境中,我們可以安裝我們的包的要求。
</>復制代碼
pip install django
pip install djangorestframework
pip install pygments # 我們將使用這個讓代碼突出顯示
注意:要隨時退出virtualenv環境,只需鍵入deactivate。有關更多信息,請參閱virtualenv文檔。
入門
好的,我們準備好獲得編碼。要開始,我們來創建一個新的項目來處理。
cd ~
django-admin.py startproject tutorial
cd tutorial
一旦完成,我們可以創建一個我們將用來創建一個簡單的Web API的應用程序。
python manage.py startapp snippets
我們需要添加我們的新snippets應用和rest_framework應用INSTALLED_APPS。我們來編輯tutorial/settings.py文件:
INSTALLED_APPS = (
</>復制代碼
...
"rest_framework",
"snippets.apps.SnippetsConfig",
)
請注意,如果你使用的Django <1.9,則需要更換snippets.apps.SnippetsConfig有snippets。
好的,我們準備好了。
創建一個可以使用的模型
為了本教程的目的,我們將首先創建一個Snippet用于存儲代碼片段的簡單模型。繼續編輯snippets/models.py文件。注意:良好的編程實踐包括評論。雖然您將在本教程代碼的存儲庫版本中找到它們,但我們在此忽略了它們,專注于代碼本身。
</>復制代碼
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
LEXERS = [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)
title = models.CharField(max_length=100, blank=True, default="")
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",)
我們還需要為我們的代碼段模型創建初始遷移,并首次同步數據庫。
</>復制代碼
python manage.py makemigrations snippets
python manage.py migrate
創建一個Serializer類
我們需要開始使用Web API的第一件事是提供一種將代碼段實例序列化和反序列化為表示形式的方式json。我們可以通過聲明與Django表單非常相似的序列化器來做到這一點。在snippets命名的目錄中創建一個文件,serializers.py并添加以下內容。
</>復制代碼
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
code = serializers.CharField(style={"base_template": "textarea.html"})
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default="python")
style = serializers.ChoiceField(choices=STYLE_CHOICES, default="friendly")
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
return Snippet.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.title = validated_data.get("title", instance.title)
instance.code = validated_data.get("code", instance.code)
instance.linenos = validated_data.get("linenos", instance.linenos)
instance.language = validated_data.get("language", instance.language)
instance.style = validated_data.get("style", instance.style)
instance.save()
return instance
使用Serializer
在我們進一步了解之前,我們將熟悉使用我們的新的Serializer類。讓我們進入Django shell。
</>復制代碼
python manage.py shell
現在,我們將以下幾個方法導入進去后,可以創建一些代碼片段來測試以下。
</>復制代碼
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
# 創建數據
snippet = Snippet(code="foo = "bar"
")
snippet.save()
snippet = Snippet(code="print "hello, world"
")
snippet.save()
我們現在有幾個片段實例可以嘗試。我們來看看序列化這些實例之一。
</>復制代碼
###
該代碼是把剛剛保存的數據snippet對象,經過序列化保存成一個字典
snippet = Snippet(code="print "hello, world"
")
snippet.save()
###
serializer = SnippetSerializer(snippet)
serializer.data
# {"id": 2, "title": u"", "code": u"print "hello, world"
", "linenos": False, "language": u"python", "style": u"friendly"}
此時,我們將模型實例轉換為Python的數據類型。要完成序列化過程需要我們將數據渲染成json。
</>復制代碼
# 將字典轉換成json格式
content = JSONRenderer().render(serializer.data)
content
# "{"id": 2, "title": "", "code": "print "hello, world"
", "linenos": false, "language": "python", "style": "friendly"}"
反序列化是類似的。首先我們將一個流解析成Python支持數據類型。
# 將json轉換成字典格式
from django.utils.six import BytesIO
stream = BytesIO(content)
data = JSONParser().parse(stream)
然后我們將這些本機數據類型恢復到完全填充的對象實例中
serializer = SnippetSerializer(data=data)
serializer.is_valid() # 驗證數據是否符合要求
# True
serializer.validated_data # 驗證后的數據
# OrderedDict([("title", ""), ("code", "print "hello, world"
"), ("linenos", False), ("language", "python"), ("style", "friendly")])
serializer.save() # 保存數據
#
請注意API與表單的使用情況。當我們開始編寫使用我們的序列化程序的視圖時,相似性將變得更加明顯。
我們也可以序列化查詢集而不是模型實例。為此,我們只many=True需要為serializer參數添加一個標志。
</>復制代碼
serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
# [OrderedDict([("id", 1), ("title", u""), ("code", u"foo = "bar"
"), ("linenos", False), ("language", "python"), ("style", "friendly")]), OrderedDict([("id", 2), ("title", u""), ("code", u"print "hello, world"
"), ("linenos", False), ("language", "python"), ("style", "friendly")]), OrderedDict([("id", 3), ("title", u""), ("code", u"print "hello, world""), ("linenos", False), ("language", "python"), ("style", "friendly")])]
使用ModelSerializers
SnippetSerializer類復制Snippet模型中大量信息。如果我們可以保持我們的代碼更簡潔,那就更好。
與Django提供的Form類和ModelForm類一樣,REST框架包括Serializer類和ModelSerializer類。
我們來使用ModelSerializer該類重構我們的serializer 。再次打開該文件snippets/serializers.py,并用SnippetSerializer以下代碼替換該類。
</>復制代碼
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ("id", "title", "code", "linenos", "language", "style")
serializer具有的一個不錯的屬性是可以通過打印其表示來檢查序列化器實例中的所有字段。打開Django shell python manage.py shell,然后嘗試以下操作:
</>復制代碼
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))
# SnippetSerializer():
# id = IntegerField(label="ID", read_only=True)
# title = CharField(allow_blank=True, max_length=100, required=False)
# code = CharField(style={"base_template": "textarea.html"})
# linenos = BooleanField(required=False)
# language = ChoiceField(choices=[("Clipper", "FoxPro"), ("Cucumber", "Gherkin"), ("RobotFramework", "RobotFramework"), ("abap", "ABAP"), ("ada", "Ada")...
# style = ChoiceField(choices=[("autumn", "autumn"), ("borland", "borland"), ("bw", "bw"), ("colorful", "colorful")...
重要的是要記住,ModelSerializer類不會做任何特別神奇的事情,它們只是創建序列化器類的快捷方式:
一組自動確定的字段。
簡單的默認實現create()和update()方法。
使用我們的Serializer編寫正常的Django視圖
我們來看看我們如何使用我們的新的Serializer類編寫一些API視圖。目前我們不會使用任何REST框架的其他功能,我們只需將視圖編寫為常規的Django視圖。
編輯snippets/views.py文件,并添加以下內容。
</>復制代碼
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
我們API本來是一個視圖函數,支持監聽所有已有的代碼或者新建的代碼片段
</>復制代碼
@csrf_exempt
def snippet_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == "GET":
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JsonResponse(serializer.data, safe=False)
elif request.method == "POST":
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
# serializer.data 數據創建成功后所有數據
return JsonResponse(serializer.data, status=201)
# serializer.errors 錯誤信息
return JsonResponse(serializer.errors, status=400)
請注意,因為我們希望能夠從不具有CSRF令牌的客戶端對此視圖進行POST,因此我們需要將視圖標記為csrf_exempt。這不是你通常想要做的事情,REST框架視圖實際上比這更有明確的行為,但它現在將為我們的目的而做。
我們還需要一個與單個代碼片段對應的視圖,并可用于檢索,更新或刪除該片段
</>復制代碼
@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)
return JsonResponse(serializer.errors, status=400)
elif request.method == "DELETE":
snippet.delete()
return HttpResponse(status=204)
最后我們需要把這些觀點連接起來。創建snippets/urls.py文件:
</>復制代碼
from django.conf.urls import url
from snippets import views
urlpatterns = [
url(r"^snippets/$", views.snippet_list),
url(r"^snippets/(?P[0-9]+)/$", views.snippet_detail),
]
我們還需要在tutorial/urls.py文件中連接根urlconf ,以包含我們的片段應用程序的URL。
</>復制代碼
from django.conf.urls import url, include
urlpatterns = [
url(r"^", include("snippets.urls")),
]
值得注意的是,我們目前還沒有正確處理好幾個邊緣案例。如果我們發送格式錯誤json,或者如果使用視圖不處理的方法發出請求,不過,按照現在這樣做,那么我們最終會出現500“服務器錯誤”響應。
測試我們在Web API上的第一次嘗試
現在我們可以啟動一個服務我們的代碼片段的示例服務器。
退出shell...
quit()
并啟動Django的開發服務器。
</>復制代碼
python manage.py runserver
Validating models...
0 errors found
Django version 1.11, using settings "tutorial.settings"
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
在另一個終端窗口中,我們可以測試服務器。
我們可以使用curl或httpie來測試我們的API 。Httpie是用Python編寫的用戶友好的http客戶端。我們來安裝
您可以使用pip安裝httpie:
pip install httpie
最后,我們可以得到所有片段的列表:
</>復制代碼
http http://127.0.0.1:8000/snippets/HTTP/1.1 200 OK...[
{
"id": 1,
"title": "",
"code": "foo = "bar"
",
"linenos": false,
"language": "python",
"style": "friendly"
},
{
"id": 2,
"title": "",
"code": "print "hello, world"
",
"linenos": false,
"language": "python",
"style": "friendly"
}]
或者我們可以通過引用其id來獲取特定的代碼段:
</>復制代碼
http http://127.0.0.1:8000/snippets/2/
HTTP/1.1 200 OK
...
{
"id": 2,
"title": "",
"code": "print "hello, world"
",
"linenos": false,
"language": "python",
"style": "friendly"
}
同樣,您可以通過在Web瀏覽器中訪問這些URL來顯示相同的json。
我們現在在哪
我們到目前為止還行,我們有一個類似于Django的Forms API和一些常規Django視圖的序列化API。
我們的API視圖目前沒有特別的特別之處,除了提供json響應外,還有一些錯誤處理我們仍然想要清理的邊緣情況,但它是一個運行良好的Web API。
我們將在本教程的第2部分中看到我們如何開始改進事情。
Django REST FrameWork中文文檔目錄:
Django REST FrameWork 中文教程1:序列化
Django REST FrameWork 中文教程2:請求和響應
Django REST FrameWork 中文教程3:基于類的視圖
Django REST FrameWork 中文教程4:驗證和權限
Django REST FrameWork 中文教程5:關系和超鏈接API
Django REST FrameWork 中文教程6: ViewSets&Routers
Django REST FrameWork 中文教程7:模式和客戶端庫
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/45451.html
摘要:目前我們的中的關系通過使用主鍵來表示。在本教程的這一部分中,我們將改進的內聚力和可發現性,而不是使用超鏈接來進行關系。將相關實體嵌套在父表示內。 目前我們的API中的關系通過使用主鍵來表示。在本教程的這一部分中,我們將改進API的內聚力和可發現性,而不是使用超鏈接來進行關系。 為我們的API的根創建一個端點現在我們有snippets和users的端點,但是我們的API沒有一個入口點。要...
摘要:目前我們的中的關系通過使用主鍵來表示。在本教程的這一部分中,我們將改進的內聚力和可發現性,而不是使用超鏈接來進行關系。將相關實體嵌套在父表示內。 目前我們的API中的關系通過使用主鍵來表示。在本教程的這一部分中,我們將改進API的內聚力和可發現性,而不是使用超鏈接來進行關系。 為我們的API的根創建一個端點現在我們有snippets和users的端點,但是我們的API沒有一個入口點。要...
摘要:目前我們的中的關系通過使用主鍵來表示。在本教程的這一部分中,我們將改進的內聚力和可發現性,而不是使用超鏈接來進行關系。將相關實體嵌套在父表示內。 目前我們的API中的關系通過使用主鍵來表示。在本教程的這一部分中,我們將改進API的內聚力和可發現性,而不是使用超鏈接來進行關系。 為我們的API的根創建一個端點現在我們有snippets和users的端點,但是我們的API沒有一個入口點。要...
摘要:看起來不錯再次,它現在仍然非常類似于基于功能的視圖。我們還需要重構一下我們使用基于類的視圖。中文文檔目錄中文教程序列化中文教程請求和響應中文教程基于類的視圖中文教程驗證和權限中文教程關系和超鏈接中文教程中文教程模式和客戶端庫 我們也可以使用基于類的視圖編寫我們的API視圖,而不是基于函數的視圖。我們將看到這是一個強大的模式,允許我們重用常用功能,并幫助我們保持代碼DRY。 使用基于類的...
摘要:看起來不錯再次,它現在仍然非常類似于基于功能的視圖。我們還需要重構一下我們使用基于類的視圖。中文文檔目錄中文教程序列化中文教程請求和響應中文教程基于類的視圖中文教程驗證和權限中文教程關系和超鏈接中文教程中文教程模式和客戶端庫 我們也可以使用基于類的視圖編寫我們的API視圖,而不是基于函數的視圖。我們將看到這是一個強大的模式,允許我們重用常用功能,并幫助我們保持代碼DRY。 使用基于類的...
摘要:看起來不錯再次,它現在仍然非常類似于基于功能的視圖。我們還需要重構一下我們使用基于類的視圖。中文文檔目錄中文教程序列化中文教程請求和響應中文教程基于類的視圖中文教程驗證和權限中文教程關系和超鏈接中文教程中文教程模式和客戶端庫 我們也可以使用基于類的視圖編寫我們的API視圖,而不是基于函數的視圖。我們將看到這是一個強大的模式,允許我們重用常用功能,并幫助我們保持代碼DRY。 使用基于類的...
閱讀 2651·2021-11-22 15:24
閱讀 1384·2021-11-17 09:38
閱讀 2759·2021-10-09 09:57
閱讀 1210·2019-08-30 15:44
閱讀 2449·2019-08-30 14:00
閱讀 3550·2019-08-30 11:26
閱讀 2942·2019-08-29 16:28
閱讀 757·2019-08-29 13:56