哪有比较完整的Django-RESTful-robot framework文档 的中文文档

Django 中 REST API 的设计 - Python - 伯乐在线
& Django 中 REST API 的设计
最近学习了REST方面的知识,了解了REST 的基础、API 的设计规则等等。
在Django中,不需要自己去设计每一个API,因为djangorestframwork帮我们做了一些工作。其实设计Django REST API的框架不少,但是djangorestframwork风格更像Django,与django的集成度更高,更易上手。该框架分为model, serializer, views三层,支持权限许可等功能。
现在就边做边学习这方面的知识。 首先是准备工作: 1、安装djangorestframwork pip install
2、安装django-
在INSTALLED_APPS中添加: ‘rest_framwork’
设置 REST_FRAMEWORK
REST_FRAMEWORK = {
# Use Django's standard &code&django.contrib.auth&/code& permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE':2,
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
12345678910
REST_FRAMEWORK = {&&&&# Use Django's standard &code&django.contrib.auth&/code& permissions,&&&&# or allow read-only access for unauthenticated users.&&&&'DEFAULT_PERMISSION_CLASSES': [&&&&&&&&'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',&&&&],&&&&'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',&&&&'PAGE_SIZE':2,&&&& 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)}
在上面设置了权限,设置了结果分页,设置了过滤器。
上面配置完成,开始写代码。
一、Model就是数据库定义的模型本身 Model有article,user,category三个
class Category(models.Model):
name = models.CharField(max_length=150,unique=True,verbose_name=u'类名')
alias = models.CharField(max_length=150,verbose_name=u'英文名称')
status = models.IntegerField(default=0,choices=STATUS.items(),verbose_name=u'状态')
#Automatically set the field to now when the object is first created.
create_time = models.DateTimeField(auto_now_add=True)
parent = models.ForeignKey('self',default=None,blank=True,null=True,verbose_name=u'上级分类')
class Article(models.Model):
title = models.CharField(max_length=150,unique=True,verbose_name=u'标题')
alias = models.CharField(max_length=150,verbose_name=u'英文标题')
content = models.TextField(verbose_name=u'正文')
#when editing article,content_html will be saved automatically from content.so it can be blank
content_html = models.TextField(blank=True,verbose_name=u'正文html格式')
abstract = models.TextField(blank=True,verbose_name=u'摘要')
read_times = models.IntegerField(default=0,verbose_name=u'阅读次数')
tags = models.CharField(max_length=100,verbose_name=u'标签',help_text='用逗号隔开')
status = models.IntegerField(default=0,choices=STATUS.items(),verbose_name=u'文章状态')
#Automatically set the field to now when the object is first created
create_time = models.DateTimeField(auto_now_add=True)
pub_time = models.DateTimeField(default=datetime.now())
#Automatically set the field to now every time the object is saved.
update_time = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User,verbose_name=u'作者')
category = models.ForeignKey(Category,verbose_name=u'分类')
access = models.IntegerField(default=100,choices=ACCESS.items(),verbose_name=u'文章权限,公开或者私人可见')
12345678910111213141516171819202122232425262728
class Category(models.Model):&&&&&name = models.CharField(max_length=150,unique=True,verbose_name=u'类名')&&&&alias = models.CharField(max_length=150,verbose_name=u'英文名称')&&&&status = models.IntegerField(default=0,choices=STATUS.items(),verbose_name=u'状态')&&&&#Automatically set the field to now when the object is first created.&&&&create_time = models.DateTimeField(auto_now_add=True)&&&&parent = models.ForeignKey('self',default=None,blank=True,null=True,verbose_name=u'上级分类')&class Article(models.Model):&&&&&title = models.CharField(max_length=150,unique=True,verbose_name=u'标题')&&&&alias = models.CharField(max_length=150,verbose_name=u'英文标题')&&&&content = models.TextField(verbose_name=u'正文')&&&&#when editing article,content_html will be saved automatically from content.so it can be blank&&&&content_html = models.TextField(blank=True,verbose_name=u'正文html格式')&&&&abstract = models.TextField(blank=True,verbose_name=u'摘要')&&&&read_times = models.IntegerField(default=0,verbose_name=u'阅读次数')&&&&tags = models.CharField(max_length=100,verbose_name=u'标签',help_text='用逗号隔开')&&&&status = models.IntegerField(default=0,choices=STATUS.items(),verbose_name=u'文章状态')&&&&#Automatically set the field to now when the object is first created&&&&create_time = models.DateTimeField(auto_now_add=True)&&&&pub_time = models.DateTimeField(default=datetime.now())&&&&#Automatically set the field to now every time the object is saved.&&&&update_time = models.DateTimeField(auto_now=True)&&&&author = models.ForeignKey(User,verbose_name=u'作者')&&&&category = models.ForeignKey(Category,verbose_name=u'分类')&&&&access = models.IntegerField(default=100,choices=ACCESS.items(),verbose_name=u'文章权限,公开或者私人可见')
User Model是Django自带的Model。
二、序列化Serializer
摘自官网: Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
The serializers in REST framework work very similarly to Django’s Form and ModelForm classes. We provide a Serializer class which gives you a powerful, generic way to control the output of your responses, as well as a ModelSerializer class which provides a useful shortcut for creating serializers that deal with model instances and querysets.
从以上文字可以看出,serializer的目的是将查询集或模型实例转化为Python数据类型,从而很方便得转变为Json,XML等多种格式。
我的项目中的Serializer设计:
from rest_framework import serializers
from .models import
Category,Article
from django.contrib.auth.models import User
from django.forms import widgets
class CategorySerializer(serializers.ModelSerializer):
# Serializers define the API representation.
class Meta:
model = Category
fields = ('id','name','alias','parent','create_time','status')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username','email','last_login')
class ArticleSerializer(serializers.ModelSerializer):
category = CategorySerializer()
author = UserSerializer()
class Meta:
model = Article
fields = ('title','content','author','category','pub_time')
1234567891011121314151617181920212223
from rest_framework import serializersfrom .models import&&Category,Articlefrom django.contrib.auth.models import Userfrom django.forms import widgets&class CategorySerializer(serializers.ModelSerializer):&&&&# Serializers define the API representation.&&&&class Meta:&&&&&&&&model = Category&&&&&&&&fields = ('id','name','alias','parent','create_time','status')&class UserSerializer(serializers.ModelSerializer):&&&&class Meta:&&&&&&&&model = User&&&&&&&&fields = ('username','email','last_login')&&class ArticleSerializer(serializers.ModelSerializer):&&&&category = CategorySerializer()&&&&author = UserSerializer()&&&&class Meta:&&&&&&&&model = Article&&&&&&&&fields = ('title','content','author','category','pub_time')
在上面每个序列器都指定了Model,这样会自动生成序列化字段,这样比较方便。 在ArticleSerializer中,加入了author和category的序列化,这样做是因为当我们浏览article的信息时。会直接显示author和category的具体信息,否则就只是author和category的id。
主要使用viewset。和route ViewSet为我们提供了默认的URL结构, 使得我们能更专注于API本身。而Route能够轻松的帮我们实现URL和ViewSet之间的关联。 源代码:
class CategoryViewset(viewsets.ModelViewSet):
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
queryset = Category.objects.all()
serializer_class = CategorySerializer
def perform_create(self, serializer):
serializer.save()
class UserViewset(viewsets.ModelViewSet):
queryset = User.objects.all()
permission_classes = (IsAdminUser,)
serializer_class = UserSerializer
class ArticleViewset(viewsets.ModelViewSet):
the viewset let us can get data from api url
like:curl - H 'application/indent=4' http://localhost:8080/api/articles/
of course,we can get some author's article through:
http://localhost:8080/api/articles/?author=2(author's id)
Generally,people like to see json data,so when visit by browser,you should add
?format=json ,that is,http://localhost:8080/api/articles/?format=json
queryset = Article.objects.all()
serializer_class = ArticleSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('author','category','access','status')
1234567891011121314151617181920212223242526272829303132333435363738
views.py&class CategoryViewset(viewsets.ModelViewSet):&&&&& """&&&&This viewset automatically provides `list`, `create`, `retrieve`,&&&&`update` and `destroy` actions.&&&&&Additionally we also provide an extra `highlight` action.&&&&"""&&&&&queryset = Category.objects.all()&&&&serializer_class = CategorySerializer&&&&&def perform_create(self, serializer):&&&&&&&&serializer.save()&&class UserViewset(viewsets.ModelViewSet):&&&&queryset = User.objects.all()&&&&permission_classes = (IsAdminUser,)&&&&serializer_class = UserSerializer&&class ArticleViewset(viewsets.ModelViewSet):&&&&"""&&&&the viewset let us can get data from api url&&&&like:curl - H 'application/indent=4' http://localhost:8080/api/articles/&&&&of course,we can get some author's article through:&&&&http://localhost:8080/api/articles/?author=2(author's id)&&&&Generally,people like to see json data,so when visit by browser,you should add&&&&?format=json ,that is,http://localhost:8080/api/articles/?format=json&&&&&"""&&&&queryset = Article.objects.all()&&&&serializer_class = ArticleSerializer&&&&filter_backends = (filters.DjangoFilterBackend,)&&&&filter_fields = ('author','category','access','status')
上面使用了ModelSet是有原因的,因为它自动提供delete,create,update,list等操作,即增删该查等操作。
其次说下filter,一般都用默认的DjangoFilterBackend,此外rest-framework 提供了几个原生的 filter:
SearchFilter
filter_backends = (filters.SearchFilter,) search_fields = (‘username’, ’email’) # 指定搜索的域
请求 /api/users?search=russell。
OrderingFilter
filter_backends = (filters.OrderingFilter,) ordering_fields = (‘username’, ’email’)
请求 /api/users?ordering=account,-username。
再说下权限。
rest_framework 中提供了七种权限
AllowAny # 无限制
IsAuthenticated # 登陆用户
IsAdminUser # Admin 用户
IsAuthenticatedOrReadOnly # 非登录用户只读
DjangoModelPermissions # 以下都是根据 Django 的 ModelPremissions
DjangoModelPermissionsOrAnonReadOnly
DjangoObjectPermissions
AllowAny # 无限制IsAuthenticated # 登陆用户IsAdminUser # Admin 用户IsAuthenticatedOrReadOnly # 非登录用户只读DjangoModelPermissions # 以下都是根据 Django 的 ModelPremissionsDjangoModelPermissionsOrAnonReadOnlyDjangoObjectPermissions
把源码拿出来:
class IsAuthenticated(BasePermission):
Allows access only to authenticated users.
def has_permission(self, request, view):
return request.user and request.user.is_authenticated()
class IsAdminUser(BasePermission):
Allows access only to admin users.
def has_permission(self, request, view):
return request.user and request.user.is_staff
12345678910111213141516
class IsAuthenticated(BasePermission):&&&&"""&&&&Allows access only to authenticated users.&&&&"""&&&&&def has_permission(self, request, view):&&&&&&&&return request.user and request.user.is_authenticated()&&class IsAdminUser(BasePermission):&&&&"""&&&&Allows access only to admin users.&&&&"""&&&&&def has_permission(self, request, view):&&&&&&&&return request.user and request.user.is_staff
其实还是比较理解的,首先判断用户,如果满足就返回True。要注意我们在Viewset中设置的权限必须是一个元祖,否则会出现错误。正确写法:permission_classes = (IsAdminUser,)。元祖里可以写多个permission,但注意,元祖里的属于与的关系,即任何一个不满足都不行,而不是或的关系,具体可见如下源代码:
def check_permissions(self, request):
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
12345678910
def check_permissions(self, request):&&&&"""&&&&Check if the request should be permitted.&&&&Raises an appropriate exception if the request is not permitted.&&&&"""&&&&for permission in self.get_permissions():&&&&&&&&if not permission.has_permission(request, self):&&&&&&&&&&&&self.permission_denied(&&&&&&&&&&&&&&&&request, message=getattr(permission, 'message', None)&&&&&&&&&&&&)
当然,除了默认的权限我们也可以自定义权限:
class UserPermisson(BasePermission):
define one permission,which can limit the user operation
def has_object_permission(self, request, view, obj):
only the creater can delete,put or post
:param request:
:param view:
:param obj:
return obj == request.user or request.user.is_staff
class ArticlePermisson(BasePermission):
def has_object_permission(self, request, view, obj):
only the creater can delete,put or post
:param request:
:param view:
:param obj:
if request.method in SAFE_METHODS:
#only the authorised user can get data
return request.user.is_authenticated
return request.user == obj.author
12345678910111213141516171819202122232425262728293031
class UserPermisson(BasePermission):&&&&"""&&&&define one permission,which can limit the user operation&&&&"""&&&&&def has_object_permission(self, request, view, obj):&&&&&&&&"""&&&&&&&&only the creater can delete,put or post&&&&&&&&:param request:&&&&&&&&:param view:&&&&&&&&:param obj:&&&&&&&&:return:&&&&&&&&"""&&&&&&&&&return obj == request.user or request.user.is_staff&&class ArticlePermisson(BasePermission):&&&&def has_object_permission(self, request, view, obj):&&&&&&&&"""&&&&&&&&only the creater can delete,put or post&&&&&&&&:param request:&&&&&&&&:param view:&&&&&&&&:param obj:&&&&&&&&:return:&&&&&&&&"""&&&&&&&&if request.method in SAFE_METHODS:&&&&&&&&&&&&#only the authorised user can get data&&&&&&&&&&&&return request.user.is_authenticated&&&&&&&&&return request.user == obj.author
这里要注意,对于一个request,会优先检查permission的has_permission方法,它是对每一个request进行检查。然后才检查has_object_permission,这是对每一个object进行检查。两者的区别是前者是对每一个request请求设置的权限,后者是对数据库条目进行权限设置的,但我理解她也包含了对request的控制。
如果不满足权限要求,则返回403或者401等错误代码。
然后定义路由:
from rest_framework import routers
from .views import CategoryViewset,ArticleViewset,UserViewset
router = routers.DefaultRouter()
router.register(r'categories',CategoryViewset)
router.register(r'articles',ArticleViewset)
router.register(r'users',UserViewset)
urls.pyfrom rest_framework import routersfrom .views import CategoryViewset,ArticleViewset,UserViewset&router = routers.DefaultRouter()&router.register(r'categories',CategoryViewset)router.register(r'articles',ArticleViewset)router.register(r'users',UserViewset)
有几点说明:
1、如果在viewset设置了权限,那么必须得带上登录用户名,密码等信息;
2、如果没有设置权限,那不带用户名可以使用GET方法,但是其他操作如POST,PUT,DELETE等,也要带上登录用户名,密码等信息;
curl http://localhost:8080/api/categoriese/10/?format=json(默认为get)
curl http://localhost:8080/api/categorieses/
curl -u username:password -X PUT -d “name=dwd&alias=dw” http://localhost:8080/api/categories/10/
curl -u username:password -X delete http://localhost:8080/api/categoriese/10/
curl -u username:password -X POST -d “name=dwd&alias=dw” http://localhost:8080/api/categories/10/
打赏支持我写出更多好文章,谢谢!
打赏支持我写出更多好文章,谢谢!
任选一种支付方式
关于作者:
可能感兴趣的话题
o 256 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线用户名:jethai
文章数:343
评论数:11
访问量:330694
注册日期:
阅读量:1297
阅读量:3317
阅读量:583240
阅读量:468306
51CTO推荐博文
Python Version:&&&&&2.7.10Django Version:&&&&&1.9REST framework 3.3.2安装pip install djangopip install djangorestframeworksettings.py INSTALLED_APPS中引入rest_frameworkINSTALLED_APPS&=&[
&&&&'django.contrib.admin',
&&&&'django.contrib.auth',
&&&&'django.contrib.contenttypes',
&&&&'django.contrib.sessions',
&&&&'django.contrib.messages',
&&&&'django.contrib.staticfiles',
&&&&'app01',
&&&&'rest_framework',
]创建model, 修改mdels.pyclass&Book(models.Model):
&&&name=models.CharField(max_length=100)
&&&title=models.CharField(max_length=100)
&&&author=models.CharField(max_length=100)创建serializers.pyfrom&app01.models&import&*
from&rest_framework&import&serializers
class&BookSerializer(serializers.Serializer):
&&&&name&=&serializers.CharField(max_length=100)
&&&&title&=&serializers.CharField(max_length=100)
&&&&author&=&serializers.CharField(max_length=100)
&&&&def&create(self,&validated_data):
&&&&&&&&return&Book(**validated_data)
&&&&def&update(self,&instance,&validated_data):
&&&&&&&&instance.email&=&validated_data.get('name',&instance.name)
&&&&&&&&instance.content&=&validated_data.get('title',&instance.title)
&&&&&&&&instance.created&=&validated_data.get('author',&instance.author)
&&&&&&&&return&instancerestore_object() 3.0以上版本不支持已经被create()和update()方法代替,源码如下:(
&&&&'Serializer&`%s.%s`&has&old-style&version&2&`.restore_object()`&'
&&&&'that&is&no&longer&compatible&with&REST&framework&3.&'
&&&&'Use&the&new-style&`.create()`&and&`.update()`&methods&instead.'&%
&&&&(self.__class__.__module__,&self.__class__.__name__)
)创建基于类和函数的视图from&django.shortcuts&import&render_to_response
from&django.http&import&HttpResponse
from&app01.forms&import&*
from&rest_framework.views&import&APIView
from&app01.serializers&import&BookSerializer
from&app01.models&import&*
from&rest_framework.response&import&Response
from&rest_framework&import&generics
from&rest_framework&import&status
#&Create&your&views&here.
class&BookList(APIView):
&&&def&get(self,request,format=None):
&&&&&&books=Book.objects.all()
&&&&&&ser=BookSerializer(books,&many=True)
&&&&&&return&Response(ser.data)
&&&def&post(self,request,format=None):
&&&&&&ser=BookSerializer(data&=&request.data)
&&&&&&if&ser.is_valid():
&&&&&&&&&ser.create(ser.validated_data).save()
&&&&&&&&&return&Response(ser.data,status&=&status.HTTP_201_CREATED)
&&&&&&return&Response(ser.errors)
class&BookDetail(APIView):
&&&def&get(self,request,num,format=None):
&&&&&&b=Book.objects.get(id=num)
&&&&&&ser=BookSerializer(b)
&&&&&&return&Response(ser.data)
class&GenericBookList(generics.ListCreateAPIView):
&&&queryset&=&Book.objects.all()
&&&serializer_class&=&BookSerializer
&&&def&post(self,request,format=None):
&&&&&&ser=BookSerializer(data&=&request.data)
&&&&&&if&ser.is_valid():
&&&&&&&&&ser.create(ser.validated_data).save()
&&&&&&&&&return&Response(ser.data,status&=&status.HTTP_201_CREATED)
&&&&&&return&Response(ser.errors)
def&index(request):
&&&return&render_to_response('index.html')
def&hello(request):
&&&if&request.method&==&'POST':
&&&&&&form&=&BookForms(request.POST)
&&&&&&if&form.is_valid():
&&&&&&&&&data&=&form.cleaned_data
&&&&&&&&&title&=&data["title"]
&&&&&&&&&return&HttpResponse(title)
&&&form&=&BookForms()
&&&return&render_to_response('1.html',&{'form':form})urls.py配置from&django.conf.urls&import&url
from&django.contrib&import&admin
from&app01.views&import&*
urlpatterns&=&[
&&&&url(r'^admin/',&admin.site.urls),
&&&url(r'^$',&index),
&&&&url(r'^hello/$',&hello),
&&&&url(r'^book/$',&BookList.as_view()),
&&&&url(r'^genericbook/$',&GenericBookList.as_view()),
&&&&url(r'^book/(\d+)',&BookDetail.as_view()),
]APIViewgeneric通用视图RESTful&Request:GET/PUT/DELETE/POST/HEAD/OPTIONSPOST请求被定义为创建“从属资源”(拥有父资源的资源) (add)参考文章:本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)

我要回帖

更多关于 .net framework 文档 的文章

 

随机推荐