[oldboy-django][2深入django]rest-framework教程
# 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/
中文翻译比较好:http://www.cnblogs.com/zivwong/p/7461764.html
-- serializer序列化和反序列化
-# 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"
-- CBV
-# 使用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)
-- GCBV
-# 使用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
-- 验证和权限
-# 验证和权限
# 验证(登录)和权限 - 只有经过登录后的用户才能具备某些权限 - 自定义一些权限,来设置某些视图函数的权限 # 需求
- 增加权限: 只有登录后才能创建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之间跳转,分页
- #超链接提供模型之间的关联
存在问题:
- 访问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
}
[oldboy-django][2深入django]rest-framework教程的更多相关文章
- Django Rest Framework 教程及API向导
Django Rest Framework 教程及API向导. 一.请求(Request)REST_FRAMEWORK 中的 Request 扩展了标准的HttpRequest,为 REST_FRAM ...
- Django REST Framework 教程开篇
作者:HelloGitHub-追梦人物 欢迎来到 HelloDjango 全栈系列教程第二步--Django REST Framework 教程! 首先恭喜你完成了 HelloDjango 全栈系列教 ...
- Part 2:模型与后台管理admin站点--Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- Part 4:表单和类视图--Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- Part 7:自定义admin站点--Django从入门到精通系列教程
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...
- Django微信小程序后台开发教程
本文链接:https://blog.csdn.net/qq_43467898/article/details/83187698Django微信小程序后台开发教程1 申请小程序,创建hello worl ...
- 整合Django的信息显示框架messages framework
##主要用在view.login函数,不管登录是否成功,都会设置message变量,然后在login.html显示 from django.contrib import messages#需要导的包 ...
- PyCharm Django Python 开发环境配置 详细教程
PyCharm Django Python 开发环境配置 详细教程 1. Python 下载及安装 (1)根据需要的版本去 Python 官网(https://www.python.org/downl ...
- [Django高级]理解django中的中间件机制和执行顺序
原文来自 Understanding Django Middlewares, 这篇文章从整体上介绍了django中中间件定义,作用,和怎么样自己写中间件 –orangleliu. 注:middlewa ...
- 全面解读Python Web开发框架Django,利用Django构建web应用及其部署
全面解读Python Web开发框架Django Django是一个开源的Web应用框架,由Python写成.采用MVC的软件设计模式,主要目标是使得开发复杂的.数据库驱动的网站变得简单.Django ...
随机推荐
- 自动化构建工具gulp的基础了解
1.使用gulp的步骤 1.安装node检测是否安装好 cmd->node -v2.安装gulp 可以在npm或者在cnpm3.在node里面有个文件package.json.利用命令行npm ...
- 如何查看CRM WebUI,C4C和Hybris里的页面技术信息
CRM 在WebClient UI页面上按F2,就能看到页面的技术信息, 可以找到当前页面是哪一个BSP component实现的: C4C 在浏览器url里添加debugMode=true,然后按住 ...
- js高级笔录
1.类型转换①转换成字符串toString() ⅰBoolean 值.数字和字符串的原始值的有趣之处在于它们是伪对象,这意味着它们实际上具有属性和方法. var sColor = "red& ...
- IOS NSBundle使用(访问文件夹)
NSBundle的相关信息 1.一个NSBundle代表一个文件夹,利用NSBundle能访问对应的文件夹 2.利用mainBundle就可以访问软件资源包中的任何资源 3.模拟器应用程序的安装路径: ...
- MySQL binlog server
从5.6版本开始,可以利用 mysqlbinlog命令把远程机器的日志备份到本地目录,这样就更加方便快捷的实现一个binlog server. 环境介绍:192.168.56.100是备份服务器,19 ...
- Python实现进度条小程序
一.print()参数介绍 1.end:指定打印结束后添加的字符,默认值为换行符 for j in range(3): print('hello world') for i in range(3): ...
- Bootstrap历练实例:弹出框(popover)事件
事件 下表列出了弹出框(Popover)插件中要用到的事件.这些事件可在函数中当钩子使用. 事件 描述 实例 show.bs.popover 当调用 show 实例方法时立即触发该事件. $('#my ...
- 【转】C++ 标准库值操作迭代器的常见函数
迭代器是C++标准库中的重要组件,特别是在容器内部,没有迭代器,容器也就无所谓存在了. 例如:vector容器简而言之就是3个迭代器 start finish 以及end_of_storage vec ...
- CentOS---zookeeper安装(单机、伪集群、集群)
一:单机安装: 可以参考下面的伪集群安装方式 不同点: 不需要在data目录下创建 myid 文件 不需要配置集群 配置好后的启动和状态查询命令相同!! 二:伪集群模式 伪集群模式就是在同一主机上启动 ...
- Linux运维常用命令详解
1.ls 文件属性: -:普通文件 d:目录文件 b:块设备 c:字符设备文件 l:符号连接文件 p:命令管道 s:套接字文件 文件权限: 9位数字,每3位一组 文件硬链接次数 文 ...