# rest-framework教程 - settings.py INSTALL-APPS = [ 'snippets', # app 'rest-framework', ] - 建立model # -*- coding: utf-8 -*- from __future__ import unicode_literals 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',) - 建立serializer 麻煩 # -*- coding: utf-8 -*- from rest_framework import serializers from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES # 不繼承ModelSerializer, 本身定義create, update,這兩個函數在SnippetSerializer對象.save()執行事被調用 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,簡便 class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ('id', 'title', 'code', 'linenos', 'language', 'style') # 和上面是同樣的,ModelSerializer裏面定義了create,update方法 # 不信你執行下面語句 serializer = SnippetSerializer() print(repr(serializer)) - 添加數據(添加兩條數據) python manage.py shell >>>from snippets.models import Snippet >>> snippet = Snippet(code='foo = "bar"\n') >>> snippet.save() >>> >>> >>> snippet = Snippet(code='print "hello, world"\n') >>> snippet.save() - 使用serializer 獲得dict數據 : serializer對象.data >>> snippet = Snippet.objects.all()[1] >>> serializer = SnippetSerializer(snippet) >>> serializer.data {'style': 'friendly', 'code': u'print "hello, world"\n', 'language': 'python', 'title': u'', 'linenos': False, 'id': 2} - 使用serializer獲得Json數據 --序列化 >>> from rest_framework.renderers import JSONRenderer >>> snippet = Snippet.objects.all()[1] >>> serializer = SnippetSerializer(snippet) >>> content= JSONRenderer().render(serializer.data) >>> content '{"id":2,"title":"","code":"print \\"hello, world\\"\\n","linenos":false,"language":"python","style":"friendly"}' >>> - 使用serializer反序列化獲得字典數據 >>> from rest_framework.renderers import JSONRenderer >>> content= JSONRenderer().render(serializer.data) >>> content '{"id":2,"title":"","code":"print \\"hello, world\\"\\n","linenos":false,"language":"python","style":"friendly"}' >>> from rest_framework.parsers import JSONParser >>> data = JSONParser().parse(content) # 會報錯,由於content不是句柄(可讀) AttributeError: 'str' object has no attribute 'read' >>> f = open('a.data','wb') >>> f.write(content) >>> f.close() >>> f = open('a.data','rb') >>> data = JSONParser().parse(f) >>> data {u'style': u'friendly', u'code': u'print "hello, world"\n', u'language': u'python', u'title': u'', u'linenos': False, u'id': 2} - 使用serializer插入數據 -- data爲上面的data >>> serializer = SnippetSerializer(data=data) # 至關於插入數據 >>> serializer.is_valid() True >>> serializer.validated_data OrderedDict([(u'title', u''), (u'code', u'print "hello, world"'), (u'linenos', False), (u'language', 'python'), (u'style', 'friendly')]) >>> serializer.save() <Snippet: Snippet object> # 數據庫保存, 查看數據庫會發現已經多了一條數據 - 將多個對象序列化many=True >>> serializer = SnippetSerializer(Snippet.objects.all(), many=True) >>> serializer.data [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), Orde redDict([('id', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]) ] - 建立views -- 工程.url urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('snippets.urls')), ] -- snippets.url urlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail), ] -- 視圖函數 # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render, HttpResponse from django.http import JsonResponse from snippets.models import Snippet from snippets.serializer import SnippetSerializer # Create your views here. def snippet_list(request): if request.method == 'GET': snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return JsonResponse(serializer.data, safe=False) def snippet_detail(request, pk): 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)
官網:http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/html
中文翻譯比較好:http://www.cnblogs.com/zivwong/p/7461764.htmlpython
-- serializer序列化和反序列化shell
-# rest-framework教程 - settings.py INSTALL-APPS = [ 'snippets', # app 'rest-framework', ] - 建立model # -*- coding: utf-8 -*- from __future__ import unicode_literals 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',) - 建立serializer 麻煩 # -*- coding: utf-8 -*- from rest_framework import serializers from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES # 不繼承ModelSerializer, 本身定義create, update,這兩個函數在SnippetSerializer對象.save()執行事被調用 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,簡便 class SnippetSerializer(serializers.ModelSerializer): class Meta: model = Snippet fields = ('id', 'title', 'code', 'linenos', 'language', 'style') # 和上面是同樣的,ModelSerializer裏面定義了create,update方法 # 不信你執行下面語句 serializer = SnippetSerializer() print(repr(serializer)) - 添加數據(添加兩條數據) python manage.py shell >>>from snippets.models import Snippet >>> snippet = Snippet(code='foo = "bar"\n') >>> snippet.save() >>> >>> >>> snippet = Snippet(code='print "hello, world"\n') >>> snippet.save() - 使用serializer 獲得dict數據 : serializer對象.data >>> snippet = Snippet.objects.all()[1] >>> serializer = SnippetSerializer(snippet) >>> serializer.data {'style': 'friendly', 'code': u'print "hello, world"\n', 'language': 'python', 'title': u'', 'linenos': False, 'id': 2} - 使用serializer獲得Json數據 --序列化 >>> from rest_framework.renderers import JSONRenderer >>> snippet = Snippet.objects.all()[1] >>> serializer = SnippetSerializer(snippet) >>> content= JSONRenderer().render(serializer.data) >>> content '{"id":2,"title":"","code":"print \\"hello, world\\"\\n","linenos":false,"language":"python","style":"friendly"}' >>> - 使用serializer反序列化獲得字典數據 >>> from rest_framework.renderers import JSONRenderer >>> content= JSONRenderer().render(serializer.data) >>> content '{"id":2,"title":"","code":"print \\"hello, world\\"\\n","linenos":false,"language":"python","style":"friendly"}' >>> from rest_framework.parsers import JSONParser >>> data = JSONParser().parse(content) # 會報錯,由於content不是句柄(可讀) AttributeError: 'str' object has no attribute 'read' >>> f = open('a.data','wb') >>> f.write(content) >>> f.close() >>> f = open('a.data','rb') >>> data = JSONParser().parse(f) >>> data {u'style': u'friendly', u'code': u'print "hello, world"\n', u'language': u'python', u'title': u'', u'linenos': False, u'id': 2} - 使用serializer插入數據 -- data爲上面的data >>> serializer = SnippetSerializer(data=data) # 至關於插入數據 >>> serializer.is_valid() True >>> serializer.validated_data OrderedDict([(u'title', u''), (u'code', u'print "hello, world"'), (u'linenos', False), (u'language', 'python'), (u'style', 'friendly')]) >>> serializer.save() <Snippet: Snippet object> # 數據庫保存, 查看數據庫會發現已經多了一條數據 - 將多個對象序列化many=True >>> serializer = SnippetSerializer(Snippet.objects.all(), many=True) >>> serializer.data [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), Orde redDict([('id', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]) ] - 建立views -- 工程.url urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('snippets.urls')), ] -- snippets.url urlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail), ] -- 視圖函數 # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render, HttpResponse from django.http import JsonResponse from snippets.models import Snippet from snippets.serializer import SnippetSerializer # Create your views here. def snippet_list(request): if request.method == 'GET': snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return JsonResponse(serializer.data, safe=False) def snippet_detail(request, pk): 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)
-- request,response,fbv數據庫
-# rest-framework核心教程(request, response, api_view, APIVIEW) -- request # 繼承HttpRequest # request.data屬性相比HttpRequest.POST更靈活:處理更復雜數據且對POST,PUT,PATCH請求都有效 request.POST # Only handles form data. Only works for 'POST' method. request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods. -- response # 根據客戶端請求不一樣的數據而渲染相應數據 return Response(data) # Renders to content type as requested by the client. -- status code # 可讀性更好,並且包含錯誤信息 -- 裝飾器 -- fbv裝飾器 @api_view是 工做fbv, 對cbv沒有效果的 -- cbv裝飾器 APIView是對FBV有效果 -- 好處: a.保證了view接收到的request實例 b.會將context添加到response中 c.還會返回正確的狀態碼 -- 使用上面四個核心東西(再也不用JSONResponse) # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render, HttpResponse # from django.http import JsonResponse from rest_framework.response import Response from snippets.models import Snippet from snippets.serializer import SnippetSerializer from rest_framework.decorators import api_view from rest_framework import status @api_view(['GET','POST']) def snippet_list(request): if request.method == 'GET': snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) elif request.method == 'POST': # add snippet obj serializer = SnippetSerializer(data=request.data) # 注意這裏版本不一樣可能不同python3應該是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) -- 控制渲染給客戶端數據的格式 -- 要修改一些東西 -- 首先是要先設置url from django.conf.urls import patterns, url from rest_framework.urlpatterns import format_suffix_patterns urlpatterns = [ url(r'^snippets/$', 'snippet_list'), url(r'^snippets/(?P<pk>[0-9]+)$', 'snippet_detail'), ] urlpatterns = format_suffix_patterns(urlpatterns) -- 其次,要修改view,每一個視圖函數添加format=None參數 -- 使用 -- 默認是api (瀏覽器看到) http://127.0.0.1:8000/snippets/ -- 使用Accept頭部信息控制response返回格式: curl http://127.0.0.1:8000/snippets/ -H 'Accept: application/json' # JSON -- 經過url的後綴來控制response返回格式 curl http://127.0.0.1:8000/snippets/.json curl http://127.0.0.1:8000/snippets/.api -- 控制提交數據的格式 提示request.DATA的靈活性 之前提交數據都是經過表單提交, -d 後面接的字符串格式 "key=value" curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123" 使用Json提交 注意多了-H , -d的數據是Json curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Content-Type: application/json" -- 測試 - windows使用curl -- 下載curl https://curl.haxx.se/download.html -- 解壓將curl.exe拷貝到工程目錄 -- 執行curl http://127.0.0.1:8000/snippets/ - get -- curl http://127.0.0.1:8000/snippets/ - post -- curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"
-- CBVdjango
-# 使用CBV縮減代碼和解耦 - 使用CBV, url注意 as_view() urlpatterns = [ url(r'^snippets/$', views.SnippetList.as_view()), url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()), ] - 視圖類的編寫繼承APIVIEW, from snippets.models import Snippet from snippets.serializer import SnippetSerializer from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class SnippetList(APIView): """ List all snippets, or create a new snippet. """ def get(self, request, format=None): snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class SnippetDetail(APIView): """ Retrieve, update or delete a snippet instance. """ def get_object(self, pk): try: return Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: raise Http404 def get(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet) return Response(serializer.data) def put(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk, format=None): snippet = self.get_object(pk) snippet.delete() return Response(status=status.HTTP_204_NO_CONTENT)
-- GCBVjson
-# 使用GCBV縮減代碼, 代碼超簡單 from snippets.models import Snippet from snippets.serializer import SnippetSerializer from rest_framework import generics class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer
-- 驗證和權限windows
-# 驗證和權限 # 驗證(登陸)和權限 - 只有通過登陸後的用戶才能具有某些權限 - 自定義一些權限,來設置某些視圖函數的權限 # 需求 - 增長權限: 只有登陸後才能建立snippet, 不然只能查看, 對應的視圖函數爲Snippet_list - 增長權限: 只有代碼的建立者,才能修改, 不然只能查看, 對應的視圖函數爲Snippet_detail # 設計 - 登陸驗證 建立者owner關聯到User, 利用django rest framework 的permissions中的IsAuthoridOrReady - 建立者才能修改 - 建立者字段owner, - 建立權限類,自定義只有建立者才能修改 - 核心 - 關聯 -- models.py - serializer -- serialziers.py - 自定義權限 -- permission.py - 登陸權限 -- rest_framework.permisson.IsAuthenticatedOrReadOnly - 補充 - 頁面出現登陸button -- project level urls.py urlpatterns += [ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] - 關聯 def perform_create(self, serializer): serializer.save(owner=self.request.user) -# 實現 -- models.py # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models from django.contrib.auth.models import User from pygments.lexers import get_all_lexers from pygments.styles import get_all_styles from pygments.lexers import get_lexer_by_name from pygments.formatters.html import HtmlFormatter from pygments import highlight 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) # add two fields, one is owner field, which is used to represent the user who create the snippet # other one is highlighted field, will be used to store the highlighted HTML owner = models.ForeignKey(User, related_name="snippets", on_delete=models.CASCADE) highlighted = models.TextField() class Meta: ordering = ('created',) # overwrite save(self,) # 當save()時,須要將高亮HTML寫到highligthed裏面 def save(self, *args, **kwargs): """ Use the `pygments` library to create a highlighted HTML representation of the code snippet. """ lexer = get_lexer_by_name(self.language) linenos = self.linenos and 'table' or False options = self.title and {'title': self.title} or {} formatter = HtmlFormatter(style=self.style, linenos=linenos, full=True, **options) self.highlighted = highlight(self.code, lexer, formatter) super(Snippet, self).save(*args, **kwargs) -- serializers.py # -*- coding: utf-8 -*- from django.contrib.auth.models import User from newsnippets.models import Snippet from rest_framework import serializers class SnippetSerializer(serializers.ModelSerializer): owner = serializers.CharField(source="owner.username", read_only=True) class Meta: model = Snippet fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner') # 由於已經關聯User, 因此必定要序列化 class UserSerializer(serializers.ModelSerializer): snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all()) class Meta: model = User fields = ('id', 'username', 'snippets') -- views.py # -*- coding: utf-8 -*- from __future__ import unicode_literals from newsnippets.models import Snippet from newsnippets.serializers import SnippetSerializer from rest_framework import generics from rest_framework import permissions from newsnippets.permissions import IsOwnerOrReadOnly class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer # 只有通過驗證的request才能修改 # 沒有通過驗證的request只能查看 permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly) # 將snippet和user關聯起來,由於user是經過request傳進來的 # 解決辦法是重寫perform_create def perform_create(self, serializer): serializer.save(owner=self.request.user) class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer # def perform_create(self, serializer): # serializer.save(owner=self.request.user) permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly) from django.contrib.auth.models import User from newsnippets.serializers import UserSerializer class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetail(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer -- 登陸權限 from rest_framework import permissions.IsAuthenticatedOrReadOnly -- 自定義權限 # -*- coding: utf-8 -*- from rest_framework import permissions # 須要添加一個權限:只有建立者才能修改,或者只能查看 # 以後見權限添加到views裏面的permission_classes class IsOwnerOrReadOnly(permissions.BasePermission): """ Custom permission to only allow owners of an object to edit it. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Write permissions are only allowed to the owner of the snippet. return obj.owner == request.user -- 將權限添加到views permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly) -
-- 超連接實現不一樣model之間跳轉,分頁api
- #超連接提供模型之間的關聯 存在問題: - 訪問http://127.0.0.1:8000/users/時看到的用戶列表, 沒有提供連接,指點點擊連接能夠查看某個用戶的詳情,好比不能跳轉到http://127.0.0.1:8000/users/2 - 訪問http://127.0.0.1:8000/snippets/一樣存在問題 - 並且users 和snippets沒有跳轉 解決問題: - 設計根url(首頁/),該頁面能夠訪問全部模型(snippet和user) # views.py增長一個view , 這裏採用fbv from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.reverse import reverse @api_view(['GET']) def api_root(request, format=None): return Response({ 'users': reverse('user-list', request=request, format=format), 'snippets': reverse('snippet-list', request=request, format=format) }) # 注意還須要設置 / ---> api_root的映射關係 # 模板也已經設置了 # reverse,因此user-list是某個url的name, 以後必定要設置 # 目前訪問首頁的結果, 能夠提供了超連接跳轉到users, 和snippets Api Root GET / HTTP 200 OK Allow: OPTIONS, GET Content-Type: application/json Vary: Accept { "users": "http://127.0.0.1:8000/new/users/", "snippets": "http://127.0.0.1:8000/new/snippets/" } - 添加超連接,當點擊超連接時能夠看到高亮代碼--返回html,若是返回json,那可視化就不行了; # 返回html REST framework爲咱們提供了兩種方式來呈現HTML,一種是使用已有的模板(咱們平時開發Django更經常使用的那種方式),另外一種就是使用已經構建好的HTML代碼。在這裏咱們會使用第二種方法 剛纔已經說了每次保存數據時都會自動更新生成新的HTML代碼,而這個由pygments生成的代碼就保存在Snippet下的highlighted,因此有瀏覽器渲染並呈現highlighted下的HTML代碼就好了。 renderer_classes = (renderers.StaticHTMLRenderer,) # 編寫GCBV from rest_framework import renderers from rest_framework.response import Response class SnippetHighlight(generics.GenericAPIView): queryset = Snippet.objects.all() renderer_classes = (renderers.StaticHTMLRenderer,) def get(self, request, *args, **kwargs): snippet = self.get_object() return Response(snippet.highlighted) # 編寫url url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()), # 測試 瀏覽器輸入: http://127.0.0.1:8000/new/snippets/1/highlight/ - 將高亮代碼超連接添加到new/snippet/1/頁面 # 修改SnippetSerailizer添加一個highlight字段,而且設置值爲超連接, highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html') 注意view_name參數,命名空間, format="html", html顯示高亮代碼 # fields fields = ('url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style') 注意多了個url, highlight # 測試 http://127.0.0.1:8000/new/snippets/1/ 能夠看到 { "url": "http://127.0.0.1:8000/new/snippets/1/", "id": 1, "title": "test 1", "highlight": "http://127.0.0.1:8000/new/snippets/1/highlight/", "code": "a = 2", "linenos": true, "language": "python3", "style": "friendly", "owner": "lzp" } - 將snippet超連接添加到user頁面, 便可以看到 snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True) # 測試 http://127.0.0.1:8000/new/users/ HTTP 200 OK Allow: GET, HEAD, OPTIONS Content-Type: application/json Vary: Accept [ { "url": "http://127.0.0.1:8000/new/users/1/", "id": 1, "username": "lzp", "snippets": [ "http://127.0.0.1:8000/new/snippets/1/" # 能夠看到全部snippets的超連接 ] } ] - 分頁 REST_FRAMEWORK = { 'PAGE_SIZE': 10 }