Архитектура restful api на pyramid — приемы проектирования...
TRANSCRIPT
![Page 1: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/1.jpg)
Архитектура RESTful API на Pyramid
приёмы проектирования
![Page 2: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/2.jpg)
Типичный проект
API
Mobile AppsAdmin PanelWeb Site
BackgroundWorkers
Data Sources
![Page 3: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/3.jpg)
Типичный проект
API
Mobile AppsAdmin PanelWeb Site
BackgroundWorkers
Data Sources
![Page 4: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/4.jpg)
Слои
Данные
Бизнес логика
Представление
![Page 5: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/5.jpg)
Слои
Данные
Бизнес логика
Представление
Model
Controller
View
![Page 6: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/6.jpg)
Слои
Данные
Бизнес логика
Представление
Model
Controller
View
Store
Resource
View
![Page 7: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/7.jpg)
Resource
![Page 8: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/8.jpg)
Resource
―Унифицированный интерфейс к данным
![Page 9: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/9.jpg)
Resource
―Унифицированный интерфейс к данным
―Унифицированные исключения
![Page 10: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/10.jpg)
Resource
―Унифицированный интерфейс к данным
―Унифицированные исключения
―Независимость от представления
![Page 11: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/11.jpg)
Traversal
![Page 12: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/12.jpg)
Traversal
child = parent['child']assert child.__name__ == 'child'assert child.__parent__ is parent
![Page 13: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/13.jpg)
Traversal
child = parent['child']assert child.__name__ == 'child'assert child.__parent__ is parent
GET /users/1/
root['users']['1']
![Page 14: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/14.jpg)
Traversal
child = parent['child']assert child.__name__ == 'child'assert child.__parent__ is parent
GET /users/1/ -> 404 Not Found
root['users']['1'] -> KeyError
![Page 15: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/15.jpg)
Traversal
class Root(object): """ API root resource """
def __getitem__(self, name): if name == 'users': return Users(name, self) raise KeyError(name)
class Users(object): """ Collection of users """
def __init__(self, name, parent): self.__name__ = name self.__parent__ = parent
![Page 16: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/16.jpg)
TraversalKit
from traversalkit import Resource, DEC_ID
class Root(Resource): # / """ API root resource """
@Root.mount('users') # /users/class Users(Resource): """ Collection of users """
@Users.mount_set(DEC_ID) # /users/{^[0-9]+$}/class User(Resource): """ Particular user """
![Page 17: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/17.jpg)
Коллекции
class Articles(Resource):
def get_list(self, offset=0, limit=10): pass
def get_map(self, ids): pass
def create(self, title, body): pass
![Page 18: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/18.jpg)
Элементы
@Articles.mount_set(DEC_ID)class Article(Resource):
def update(self, title, body): pass
def delete(self): pass
![Page 19: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/19.jpg)
Загрузка элемента
from ..store import db
@Articles.mount_set(DEC_ID)class Article(Resource):
__not_exist__ = db.NoResultFound
def on_init(self, data=None): if data is None: # Created via __getitem__ session = db.Session() data = session \ .query(db.Article) \ .filter(db.Article.id == int(self.__name__)) \ .one() self.data = data
![Page 20: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/20.jpg)
Загрузка списка
from ..store import db
class Articles(Resource):
def get_list(self, offset=0, limit=50): session = db.Session() query = session \ .query(db.Article) \ .limit(limit) \ .offset(offset) \ .order_by(db.Article.created_at)
return [ self.get(str(item.id), item) for item in query.all() ]
![Page 21: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/21.jpg)
Иерархия
@Root.mount('articles') # All articlesclass Articles(Resource): """ Collection of articles """
@Article.mount('comments') # Article's commentsclass Comments(Resource): """ Collection of comments """
![Page 22: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/22.jpg)
Иерархия
@Root.mount('articles') # All [email protected]('articles') # User's articlesclass Articles(Resource): """ Collection of articles """
@Article.mount('comments') # Article's [email protected]('comments') # User's commentsclass Comments(Resource): """ Collection of comments """
![Page 23: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/23.jpg)
ACL
from pyramid.security import Allow, Everyone, Authenticated
class Articles(Resource):
__acl__ = [ (Allow, Everyone, 'read'), (Allow, Authenticated, 'create'), (Allow, 'group:moderators', ('update', 'delete')), ]
@Articles.mount_set(DEC_ID)class Article(Resource):
def __acl__(self): user_id = str(self.data.user_id) return [(Allow, user_id, ('update', 'delete'))]
![Page 24: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/24.jpg)
ACL
from pyramid.security import \ Allow, Everyone, Authenticated, DENY_ALL
@Article.mount('comments')class Comments(Resource):
__acl__ = [ (Allow, Everyone, 'read'), (Allow, Authenticated, 'create'), (Allow, 'group:moderators', ('update', 'delete')), DENY_ALL, # Stop inheritance ]
![Page 25: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/25.jpg)
Валидация
from .. import validation
class Articles(Resource, validation.Mixin):
@validation.set_schema(validation.schema.Article) def create(self, title, body): pass
def create_article(context, request): article = context.validated.create(request.json)
![Page 26: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/26.jpg)
Views
from pyramid.view import view_config
from ..resources import Articles
@view_config(context=Articles, request_method='GET', permission='read')def list_articles(context, request): articles = context.validated.get_list(request.GET) return { 'articles': articles, }
![Page 27: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/27.jpg)
Views
from pyramid.view import view_config
from ..resources import Articles
@view_config(context=Articles, request_method='GET', permission='read')def list_articles(context, request): articles = context.validated.get_list(request.GET) users = request.root['users'].get_map( set(a.data.user_id for a in articles) ) return { 'articles': articles, 'users': users, }
![Page 28: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/28.jpg)
Сериализация
class Article(Resource):
def __json__(self, *_): return { 'id': self.data.id, 'title': self.data.title, 'body': self.data.body, }
![Page 29: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/29.jpg)
Обработка ошибок
from pyramid.view import view_configfrom pyramid.security import NO_PERMISSION_REQUIRED
from ..resources import ResourceExceptionfrom ..validation import Invalid
@view_config(context=ResourceException, permission=NO_PERMISSION_REQUIRED)def resource_exception(context, request): request.response.status_int = 400 return {'error': context}
@view_config(context=Invalid, permission=NO_PERMISSION_REQUIRED)def validation_exception(context, request): request.response.status_int = 422 return {'error': context}
![Page 30: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/30.jpg)
Обработка ошибок
400422
Ошибка бизнес логикиНевалидные данные
![Page 31: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/31.jpg)
Обработка ошибок
400422403404
Ошибка бизнес логикиНевалидные данныеНет прав доступаРесурса не существует
![Page 32: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/32.jpg)
Обработка ошибок
400422403404405
Ошибка бизнес логикиНевалидные данныеНет прав доступаРесурса не существуетОшибка контекста
![Page 33: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/33.jpg)
Обработка ошибок
400422403404405500
Ошибка бизнес логикиНевалидные данныеНет прав доступаРесурса не существуетОшибка контекстаВсё сломалось
![Page 34: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/34.jpg)
Тесты
ResourceViewWSGI
![Page 35: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/35.jpg)
Тесты
ResourceViewWSGI
Бизнес логика, иерархия
![Page 36: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/36.jpg)
Тесты
ResourceViewWSGI
Бизнес логика, иерархияВалидация, связанные данные, сессия
![Page 37: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/37.jpg)
Тесты
ResourceViewWSGI
Бизнес логика, иерархияВалидация, связанные данные, сессияИнтеграция, ACL
![Page 38: Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев](https://reader031.vdocuments.net/reader031/viewer/2022021921/58f323d71a28abf00a8b45f3/html5/thumbnails/38.jpg)
Вопросы?