Django REST实现步骤

来源:互联网 发布:跟单软件免费 编辑:程序博客网 时间:2024/05/17 21:42

安装django及djangorestframework

pip install django
pip install djangorestframework
(注:本文环境python2.7.9, django 1.9.2, djangorestframework 3.3.3)

创建django rest project及app

与创建django项目方法一样

修改setting.py

INSTALLED_APPS添加rest_framework
INSTALLED_APPS = [    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'rest_framework',    ...]
添加rest全局配置REST_FRAMEWORK
REST_FRAMEWORK = {    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),    'PAGE_SIZE': 10}

添加自己的model

models.py文件中定义question model:
class Question(mongoengine.document.Document):    question = mongoengine.fields.StringField(max_length = 10240, required = True)    answer = mongoengine.fields.BooleanField(required = True)    reason = mongoengine.fields.StringField(max_length = 1024)    meta = {"db_alias": "wdbk", 'clooection': 'question'}

定义序列化类

新建serializers.py文件,定义序列化类,有三种方法:

(1) 继承于rest_framework.serializers.Serializer

class QuestionSerializer(serializers.Serializer):    def create(self, validated_data):        return Question.objects.create(**validated_data)    def update(self, instance, validated_data):        instance.question = validated_data.get('question', instance.question)        instance.answer = validated_data.get('answer', instance.answer)        instance.reason = validated_data.get('reason', instance.reason)        instance.save()        return instance

(2) 继承 于rest_framework.serializers.ModelSerializer

class QuestionSerializer(<span style="font-family: Arial, Helvetica, sans-serif;">serializers.ModelSerializer</span>):    class Meta:        model = Question        fields = ('question', 'answer', 'reason') 
(3) 在视图中自己实现序列化
可以参考http://www.django-rest-framework.org/tutorial/1-serialization/#writing-regular-django-views-using-our-serializer

定义REST视图

有以下几种方法实现rest视图:
(1) 函数视图
自定义函数,使用api_view装饰器,在函数内部处理GET、POST等请求
from rest_framework import statusfrom rest_framework.decorators import api_viewfrom rest_framework.response import Responsefrom models import Questionfrom serializers import QuestionSerializer@api_view(['GET', 'POST'])def question_list(request):    if request.method == 'GET':        questions = Question.objects.all()        serializer = QuestionSerializer(questions, many=True)        return Response(serializer.data)    elif request.method == 'POST':        serializer = QuestionSerializer(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)
然后在urls.py中加入视图函数即可
(2) 基于类的视图
定义类继承于APIView,并实现get, post等方法
from models import Questionfrom serializers import QuestionSerializerfrom django.http import Http404from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom rest_framework import statusclass QuestionList(APIView):    def get(self, request, format=None):        questions = Question.objects.all()        serializer = QuestionSerializer(questions, many=True)        return Response(serializer.data)    def post(self, request, format=None):        serializer = QuestionSerializer(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)
在urls.py中添加视图类
urlpatterns += [    url(r'^questions/$', views.QuestionList.as_view()),]
(3)使用ViewSet
参考http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/#tutorial-6-viewsets-routers
下面是我的ViewSet
from models import Questionfrom permission import IsOwnerOrReadOnlyfrom rest_framework.response import Responsefrom rest_framework import statusclass QuestionViewSet(viewsets.ModelViewSet):    """    This viewset automatically provides `list`, `create`, `retrieve`, `update` and `destroy` actions.    Additionally we also provide an extra `initialization` and `random` action.    """    queryset = Question.objects.all()    serializer_class = QuestionSerializer    #permission_classes = (permissions.IsAuthenticatedOrReadOnly,)    #                      IsOwnerOrReadOnly,)    @list_route()    def initialization(self, request):        try:            excel = xlrd.open_workbook(settings.STATIC_ROOT + '/data/question.xls')            sheet_question = excel.sheet_by_name('question')        except Exception, e:            return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)        try:            Question.objects().delete()            for i in range(1, sheet_question.nrows):                values = sheet_question.row_values(i)                c = Question.objects(question=values[0])                c.update(upsert = True,                         set__question = values[0],                         set__answer = bool(values[1]),                         set__reason = values[2])        except Exception, e:            return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)        return Response(status=status.HTTP_201_CREATED)    def get_object(self):        pk = self.kwargs.get('pk')        question = Question.objects(question=pk)        #if question:        return question[0]    @list_route()    def random(self, request):        total = Question.objects.count()        # 随机生成index        randimskip = random.randint(1, total-1)        # 查询问题        questions = Question.objects.skip(randimskip).limit(20)        serializer = self.get_serializer(questions, many=True)        return Response(serializer.data)

上面的viewset中,有两个函数使用的@list_router装饰器,其表示这是用户自定义的额外的方法。因为有时候viewset自动生成的list, create, retrive, update, delete等方法不能满足我们的需要,比如需要随机查询数据库中的20条记录。在django debug输出中可以看到自定义方法的rest资源路径:

Using the URLconf defined in web.urls, Django tried these URL patterns, in this order:^static/(?P<path>.*)$^admin/^rest/ ^ ^$ [name='api-root']^rest/ ^ ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']^rest/ ^ ^questions/$ [name='question-list']^rest/ ^ ^questions\.(?P<format>[a-z0-9]+)/?$ [name='question-list']^rest/ ^ ^questions/initialization/$ [name='question-initialization']^rest/ ^ ^questions/initialization\.(?P<format>[a-z0-9]+)/?$ [name='question-initialization']^rest/ ^ ^questions/random/$ [name='question-random']^rest/ ^ ^questions/random\.(?P<format>[a-z0-9]+)/?$ [name='question-random']^rest/ ^ ^questions/(?P<pk>[^/.]+)/$ [name='question-detail']^rest/ ^ ^questions/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='question-detail']^rest/ ^api-auth/

路由

在urls.py中添加如下代码:
from views import QuestionViewSetfrom rest_framework.routers import DefaultRouterrouter = DefaultRouter()# need to set base_name,otherwise will report:AttributeError: 'QuerySet' object has no attribute 'model'router.register(r'questions', QuestionViewSet, r'question')urlpatterns = [    ...    url(r'^', include(router.urls)), ]


REST安全认证

客户端有三种认证方式BasicAuthentication、SessionAuthentication、TokenAuthentication
需要在setting.py中配置默认的认证类:
REST_FRAMEWORK = {    # three auth way: session,basic,token    'DEFAULT_AUTHENTICATION_CLASSES': (        'rest_framework.authentication.BasicAuthentication',        'rest_framework.authentication.SessionAuthentication',        'rest_framework.authentication.TokenAuthentication',    ),    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),    'PAGE_SIZE': 10}
具体可以参考http://www.django-rest-framework.org/api-guide/authentication/#authentication
如果要使用djangorestframe提供的认证登录界面,需要在urlpatterns中添加:
urlpatterns = [    ...    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),]

monodb + djangorestframework

为了在djangorestframework中使用mongodb, 需要mongoengine和django-rest-framework-mongoengine
pip install mongoengine
pip install django-rest-framework-mongoengine
序列化类这样写
# -*- coding: utf-8 -*-from rest_framework_mongoengine.serializers import DocumentSerializerfrom models import *class QuestionSerializer(DocumentSerializer):    """    使用ModelSerializer实现序列化    """    class Meta:        model = Question        fields = ('question', 'answer', 'reason')        #depth = 2    def create(self, validated_data):        return Question.objects.create(**validated_data)    def update(self, instance, validated_data):        instance.question = validated_data.get('question', instance.question)        instance.answer = validated_data.get('answer', instance.answer)        instance.reason = validated_data.get('reason', instance.reason)        instance.save()        return instance
当然最笨的方法就是不使用mongoengine,利用pymongo自己封装model,并且不使用viewset实现视图

http://blog.csdn.net/fragmentalice

0 0
原创粉丝点击