看了极客学院的【Django 开发——API 设计】,因为年代久远版本太老,代码调试了一上午没调试通,决定放弃视频学习,看一些最近的技术博客或者官方文档
上图中可以看出python版本:2.7.5
django版本1.9.4
rest_framework版本3.6.2
官方文档
使用Django REST framework的原因如下:
Web browsable API 对项目来说有很大的可用性;
权限验证包括 OAuth1a and OAuth2;
支持ORM以及non-ORM两个数据源的 Serialization;
若不需要特别强大的功能,直接使用 regular function-based views
扩展文档以及社区讨论;
被大公司使用和信任,比如 Mozilla and Eventbrite;
通过python manage.py createsuperuser添加用户
通过登录页面,登陆之后,可以通过post添加用户
curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
获取用户列表
pip install httpie
http -a admin:password http://127.0.0.1:8000/users/
Serialization序列化
实例:creating a simple pastebin code highlighting Web API(创建一个简单的类似于pastebin的代码高亮web api)
【1】开始创建
django-admin.py startproject myTest
python manage.py startapp myLesson
在myTest/setting.py中INSTALL_APPS添加:
'rest_framework'
'myLesson.apps.MylessonConfig'
【2】创建model
在myLesson中添加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 MyLesson(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 makemigration myLesson
python manage.py migrate
models数据模型:
每个应用一般都会定义一个或多个models,这个数据models实际上是与数据库相关的,models中的每个属性都是数据库当中的一个字段,每个字段都是数据库中的一个列。在models中定义的每个类相当于数据库当中的table
每个class属性斗士models中的某些字段类的实例,并且每个人字段类都有一些参数
【3】创建序列化类
创建web api,第一件事就是序列化和反序列化,以便MyLesson实例可以转化为可表述的内容,例如json
from rest_framework import serializers from myLesson.models import MyLesson, LANGUAGE_CHOICES, STYLE_CHOICES class MyLessonSerializer(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 `MyLesson` instance, given the validated data. """ return MyLesson.objects.create(**validated_data) def update(self, instance, validated_data): """ Update and return an existing `MyLesson` 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
该序列化类的前面部分,定义了要序列化和反序列化的类型,creat和update方法定义了如何创建和修改正确的对象实例。
ModelSerializer类可以来快速生成序列化部分
class MyLessonSerializer(serializers.ModelSerializer): class Meta: model = MyLesson fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
ModelSerializer类自动决定成员的属性,并有默认的create()和update()方法
【4】使用Serializers
python manage.py shell 进入终端交互模式
#在shell终端输入: from myLesson.models import MyLesson from myLesson.serializers import MyLessonSerializer from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser myLesson = Mylesson(code='foo = "bar" ') myLesson.save() serializer = MyLessonSerializer(myLesson) serializer.data #此时输出的是python原生的数据类型 content = JSONRenderer().render(serializer.data) content #此时输出的Json数据类型 from django.utils.six import BytesIO stream = BytesIO(content) data = JSONParser().parse(stream) #反序列化,转化为python原生的数据类型 serializer = MyLessonSerializer(data=data) serializer.is_valid() # True serializer.validated_data # OrderedDict([('title', ''), ('code', 'print "hello, world" '), ('linenos', False), ('language', 'python'), ('style', 'friendly')]) serializer.save() #转换为对象实例 serializer = MyLessonSerializer(MyLesson.objects.all(), many=True) serializer.data #序列化querysets
【5】用Serializer写一个的Django views
不使用rest framework的其他特性,仅编写正常的django view
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 myLesson.models import MyLesson from myLesson.serializers import MyLessonSerializer @csrf_exempt def MyLesson_list(request): """ List all code MyLesson, or create a new myLesson. """ if request.method == 'GET': myLesson = MyLesson.objects.all() serializer = MylessonSerializer(myLesson, many=True) return JsonResponse(serializer.data, safe=False) elif request.method == 'POST': data = JSONParser().parse(request) serializer = MyLessonSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400) @csrf_exempt def MyLesson_detail(request, pk): """ Retrieve, update or delete a code MyLesson. """ try: myLesson = MyLesson.objects.get(pk=pk) except MyLesson.DoesNotExist: return HttpResponse(status=404) if request.method == 'GET': serializer = MyLessonSerializer(myLesson) return JsonResponse(serializer.data) elif request.method == 'PUT': data = JSONParser().parse(request) serializer = MyLessonSerializer(myLesson, data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data) return JsonResponse(serializer.errors, status=400) elif request.method == 'DELETE': myLesson.delete() return HttpResponse(status=204) 在myLesson中创建urls.py from django.conf.urls import url from myLesson import views urlpatterns = [ url(r'^myLesson/$', views.MyLesson_list), url(r'^myLesson/(?P<pk>[0-9]+)/$', views.Mylesson_detail), ]
在myTest的urls.py中添加
from django.conf.urls import url, include urlpatterns = [ url(r'^', include('myLesson.urls')), ]
测试:
http http://127.0.0.1:8000/myLesson/