Contenu connexe Similaire à Tastypie (20) Tastypie2. Outline
● 為什麼要用 Web API ?
● Tastypie 能幫我們作什麼?
● 如何開始寫 Tastypie?
● 如何強化你的 Web API?
● 如何調校你的 Tastypie?
● Tastypie 還可以怎樣改?
3. 為什麼要用 Web API ?
● 回顧一下 Request 週期
url
Request
view
model
Response
template
10. 如何開始寫 Tastypie?
1. pip install django django-tastypie mysqlpython mimeparse
2. django-admin.py startproject myApp
3. cd ./myApp
4. python manage.py startapp myApi
5. mkdir ./myApi/api && touch .
/myApi/api/__init__.py
6. vim ./myApi/api/resources.py
11. 如何開始寫 Tastypie?(cont’d)
● vim ./myApi/api/resources.py
from tastypie.resources import ModelResource
from django.contrib.auth.models import Group, User
class UserModelResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
allowed_methods = ['get']
12. 如何開始寫 Tastypie?(cont’d)
● vim ./myApp/myApi/urls.py
from django.conf.urls import patterns, include, url
from api.resources import UserModelResource
urlpatterns = patterns('',
(r'', include(UserModelResource().urls)),
)
13. 如何開始寫 Tastypie?(cont’d)
● vim ./myApp/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myApp',
'USER': 'root',
'PASSWORD': 'root',
'HOST': '127.0.0.1',
'PORT': '',
}
}
…
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
...
'tastypie',
myApi,
)
14. 如何開始寫 Tastypie?(cont’d)
● vim ./myApp/urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
…
(r'^api/', include('myApi.urls')),
)
15. 如何開始寫 Tastypie?(cont’d)
1. python manage.py syncdb
2. python manage.py runserver
3. GET http://localhost:8000/api/user/ or http:
//localhost:8000/api/user/?format=json
18. 如何強化你的 Web API?
● 先多增加兩個 API: api/resources.py
from django.contrib.auth.models import Group, User, Permission
…
class GroupModelResource(ModelResource):
class Meta:
queryset = Group.objects.all()
resource_name = 'group'
allowed_methods = ['get']
class PermissionModelResource(ModelResource):
class Meta:
queryset = Permission.objects.all()
resource_name = 'permission'
allowed_methods = ['get']
19. 如何強化你的 Web API?(cont’d)
● 再新增/修改 url:api/urls.py
from api.resources import UserModelResource,
GroupModelResource, PermissionModelResource
…
urlpatterns = patterns('',
(r'', include(UserModelResource().urls)),
(r'', include(GroupModelResource().urls)),
(r'', include(PermissionModelResource().urls)),
)
22. 如何強化你的 Web API?(cont’d)
from tastypie import fields
class UserModelResource(ModelResource):
groups = fields.ToManyField('api.resources.GroupModelResource', 'groups')
permissions = fields.ToManyField('api.resources.PermissionModelResource',
'user_permissions')
class Meta:
queryset = User.objects.all()
resource_name = 'user'
allowed_methods = ['get']
#detail_allowed_methods = ['get']
#fields = ['username', 'first_name', 'last_name', 'last_login']
excludes = ['id', 'is_active', 'date_joined', 'password', 'is_staff', 'is_superuser']
23. 如何強化你的 Web API?(cont’d)
class GroupModelResource(ModelResource):
permissions = fields.ToManyField('api.resources.
PermissionModelResource', 'permissions')
#users = fields.ToManyField('api.resources.UserModelResource', 'user_set')
users = fields.ToManyField(UserModelResource, 'user_set')
class Meta:
queryset = Group.objects.all()
resource_name = 'group'
allowed_methods = ['get']
#detail_allowed_methods = ['get']
26. 如何強化你的 Web API?(cont’d)
…
from tastypie.authorization import Authorization
class UserModelResource(ModelResource):
groups = fields.ToManyField('api.resources.GroupModelResource', 'groups', null=True)
permissions = fields.ToManyField('api.resources.PermissionModelResource',
'user_permissions', null=True)
class Meta:
...
#allowed_methods = ['get']
list_allowed_methods = ['get', 'post']
detail_allowed_methods = ['get', 'put']
...
always_return_data = True
#authentication = Authentication() # BasicAuthentication, ApiKeyAuthentication
authorization = Authorization() # ReadOnlyAuthorization, DjangoAuthorization
27. 如何強化你的 Web API?(cont’d)
class GroupModelResource(ModelResource):
permissions = fields.ToManyField('api.resources.PermissionModelResource',
'permissions', null=True)
users = fields.ToManyField('api.resources.UserModelResource', 'user_set', null=True)
class Meta:
...
list_allowed_methods = ['get', 'post']
detail_allowed_methods = ['get', 'put', 'delete']
always_return_data = True
authorization = Authorization()
30. 如何調校你的 Tastypie?(cont’d)
from tastypie.resources import ModelResource, ALL_WITH_RELATIONS
from tastypie.utils.urls import trailing_slash
from django.conf.urls import url
...
class UserModelResource(ModelResource):
…
class Meta:
...
detail_uri_name = 'username'
filtering = {
'groups': ALL_WITH_RELATIONS,
}
33. 如何調校你的 Tastypie?(cont’d)
class UserModelResource(ModelResource):
def base_urls(self):
return [
url(r"^(?P<resource_name>%s)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_list'), name="api_dispatch_list"),
url(r"^(?P<resource_name>%s)/(?P<%s>w[w/-]*)%s$" %
(self._meta.resource_name, self._meta.detail_uri_name, trailing_slash()),
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
url(r"^group/(?P<groups__name>%s)/(?P<resource_name>%s)%s$" %
(r'[w]{,80}', self._meta.resource_name, trailing_slash()),
self.wrap_view('dispatch_list'), name="api_dispatch_list"),
url(r"^group/(?P<groups__name>%s)/(?P<resource_name>%s)/(?P<%s>w[w/-]*)%s$" %
(r'[w]{,80}', self._meta.resource_name, self._meta.detail_uri_name, trailing_slash()),
self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
34. 如何調校你的 Tastypie?(cont’d)
● 似乎還差一點點
○ GET http://localhost:8000/api/group/a/user/ :
1.
"meta": {
2.
"limit": 10,
3.
"next": "/api/user/?limit=10&offset=10",
4.
"offset": 0,
5.
"previous": null,
6.
"total_count": 13
7.
}
● 需要對 get_list 作點修正,同樣
vim resources.py
36. 如何調校你的 Tastypie?(cont’d)
class BaseModelResource(ModelResource):
def get_list(self, request, **kwargs):
base_bundle = self.build_bundle(request=request)
objects = self.obj_get_list(bundle=base_bundle, **self.remove_api_resource_names(kwargs))
sorted_objects = self.apply_sorting(objects, options=request.GET)
paginator = self._meta.paginator_class(request.GET, sorted_objects,
原程式修改這邊
resource_uri=self.get_resource_list_uri(**kwargs),
limit=self._meta.limit, max_limit=self._meta.max_limit,
collection_name=self._meta.collection_name)
to_be_serialized = paginator.page()
bundles = []
for obj in to_be_serialized[self._meta.collection_name]:
bundle = self.build_bundle(obj=obj, request=request)
bundles.append(self.full_dehydrate(bundle, for_list=True))
to_be_serialized[self._meta.collection_name] = bundles
to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized)
return self.create_response(request, to_be_serialized)
38. 如何調校你的 Tastypie?(cont’d)
● 這樣就修正完畢了
○ GET http://localhost:8000/api/group/a/user/ :
1.
"meta": {
2.
"limit": 10,
3.
"next": "/api/group/a/user/?limit=10&offset=10",
4.
"offset": 0,
5.
"previous": null,
6.
"total_count": 13
7.
}