morepath

一、概述:

Morepath 是一个 Python WSGI 微框架,是模型驱动的。

二、安装:

pip install morepath (CDB python解释器中默认已安装)

三、快速开始:

# 第一种
import morepath


# 继承morepath App基类
class App(morepath.App):
    pass

# 创建一个类,作为暴露的资源对象
class Document(object):
    def __init__(self, id):
        self.id = id

# 绑定路由,返回资源实例
@App.path(path='documents/{id}', model=Document)
def get_document(id):
    return Document(id)  # query for doc

# 绑定视图函数,self为@App.path中返回的Document实例
@App.html(model=Document) 
def hello_doc(self, request):     
  return'<p>Hello document: %s!</p>'%self.id

if __name__ == '__main__':
    morepath.run(App())

# 启动服务:访问127.0.0.1:5000/documents/1   

# 第二种
import morepath


class App(morepath.App):
    pass

# 直接在类上绑定路由
@App.path(path="")
class Root(object):
    pass


@App.view(model=Root)
def hello_world(self, request):
    return "Hello world!"


if __name__ == "__main__":
    morepath.run(App())

四、Model :

任何类对象都可以作为暴露的资源

五、Paths :

# 如果不指定path则默认为 ''
@App.view(model=Overview)
def overview_default(self, request):
    return "Overview"

# path参数指定url
@App.path(model=Overview, path='overview')
def get_overview():
    return Overview()

# 获取路径参数
@App.path(model=Document, path='documents/{name}')
def get_document(name):
    return query_document_by_name(name)

# 获取query参数,"/documents?name=foo",默认为"test"
@App.path(model=Document, path='documents')
def get_document(name='test'):
    return query_document_by_name(name)

# 获取除了text之外的query参数,extra_parameters 为dict
@App.path(model=DocumentCollection, path='search')
def document_search(text='all', extra_parameters):
    return DocumentCollection(text, extra_parameters)

# 类型校验,通过默认值指定参数类型,比如id必须为数字,如果传递非数字则会404
@App.path(model=Record, path='records/{id}')
def get_record(id=0):
    return record_by_id(id)

def id_converter(id):
 return int(id)

# 自定义转换函数:可以针对路径参数,url参数
# 1. 转换逻辑
def id_convert(name):
    return str(name)
# 2. 生成一个转换函数
my_converter = morepath.Converter(decode=id_convert)
# 3. 为参数指定转换器
@App.path(model=Document, path='documents/{name}',variables=document_variables, converters=dict(name=my_converter))
def get_document(name):
    return Document(name)

# 列表转换器
@App.path(model=Days, path='days', converters=dict(d=[my_converter]))
def get_days(d):
    return Days(d)

# 运行时才知道转换器该用哪个,使用get_converters参数
def my_get_converters():
    return { 'something': int }

@App.path(path='search', model=SearchResults,
          get_converters=my_get_converters)
...


# 设置路径参数id必传: ?id=2
@App.path(model=Document, path='documents', required=['id'])
def get_record(id):
    return Document(id)

# 匹配url内容,请求:"/start/foo/bar/baz" ,absorb结果为foo/bar/baz
@App.path(model=Document, path='start', absorb=True)
def get_foo(absorb):
    return Model(absorb)

六、反向生成URL:

@App.view(model=Document)
def document_self_link(self, request):
    # 目标视图函数无name参数时
    return request.link(self')

@App.view(model=Document)
def document_self_link(self, request):
   # 目标视图函数包含name参数时
    return request.link(self, name='link')

# 反向生成url时,如果存在路径参数或者请求参数,后台默认使用getattr(obj,attr),从目标对象上获取路径参数,
# 可以通过variables参数更加灵活的获取路径参数的

# 例如:默认反向生成url时,直接从obj对象上获取name属性
@App.path(model=Document, path='documents/{name}',
          variables=lambda obj: dict(name=obj.name))
def get_document(name):
    return query_document_by_name(name)

# 你可以自定义函数
def document_variables(obj):
    return dict(name=obj.name)

@App.path(model=Document, path='documents/{name}',
          variables=document_variables)
def get_document(name):
    return query_document_by_name(name)

# 反向生成url时,统一添加前缀(仅影响反向生成的url,并不会影响系统接口,仅执行一次,后续会使用缓存)
@App.link_prefix()
def simple_link_prefix(request):
    return 'http://example.com/'

# 使用model生成link,比起实例消耗更小
@App.view(model=Document, name='class_link')
def document_self_link(self, request):
    return request.class_link(Document, variables={'name': 'Document name'})

七、Views

# 返回文本内容 或者 morepath.Response
@App.view(model=User, name='edit',request_method='GET')
def edit_user(self, request):
    return "An editing UI goes here"


# 返回html,name参数相当于在@App.path的路由后再添加"/b"
@App.html(name="b" ,model=Document,request_method='GET')
def hello_doc(self, request):
  return '<p>Hello document: %s!</p>'%self.id

# 返回json
@App.json(name="a" ,model=Document,request_method='POST')
def hello_doc(self, request):
  return {"code":200}

# 指定返回类型
@App.view(model=Document, render=morepath.render_html)
def document_default(self, request):
    return "<p>Some html</p>"

# 自定义返回类型
def render_json(content, request):
    response = morepath.Response(json.dumps(content))
    response.content_type = 'application/json'
    return response

@App.view(model=Document, render=morepath.render_json)
def document_default(self, request):
    return {'my': 'json'}

# 返回html模板
@App.html(model=Document, template='document.pt')
def document_default(self, request):
    return { 'title': self.title, 'content': self.content }


# 添加回调,在回调中设置cookie,而不用自己实例化response
@App.view(model=Document)
def document_default(self, request):
    @request.after
    def manipulate_response(response):
        response.set_cookie('my_cookie', 'cookie_data')
    return "document default"

# 合并同一个model的多个view
with App.view(model=Document) as view:
   @view()
   def document_default(self, request):
       return "default"

   @view(name="edit")
   def document_edit(self, request):
       return "edit"

# 自定义路由参数,很像fastapi的依赖
import reg

# 要求请求header中Something=special
@App.predicate(generic.view, name='something', default=None,
               index=reg.KeyIndex,
               after=morepath.LAST_VIEW_PREDICATE)
def something_predicate(request):
    return request.headers.get('Something')

@App.view(model=Document, something='special')
def document_default(self, request):
    return "Only if request header Something is set to special."


# request.view 调用路由
@App.json(model=ParticularItem)
def particular_item_default(self, request):
    return {'id': self.id}

@App.json(model=Collection)
def collection_default(self, request):
    return [request.view(item) for item in self.query()]

# 设置视图只能内部使用,不对外暴露:internal
@App.json(model=SomeOtherItem, name='extra', internal=True)
def some_other_item_extra(self, request):
    return self.name

八、Permissions权限控制:

# 定义权限控制类
class Edit(object):
    pass

# 权限校验逻辑
@App.view(model=Document, name='edit', permission=Edit)
def document_edit(self, request):
    return 'edit document'

@App.permission_rule(model=Document, permission=Edit)
def document_edit_permission(identity, model, permission):
    return identity.userid in model.allowed_users

九、Request :

request.GET   : query参数
request.POST  :Form data
request.method :请求方式
request.cookies : 获取cookie
response.set_cookie :设置cookie  

十、重定向:

@App.view(model=User, name='extra')
def redirecting(self, request):
    # request.link反向生成url
    return morepath.redirect(request.link(self, 'other'))

十一、异常处理:

# 异常捕获处理
from webob.exc import HTTPNotFound

@App.view(model=HTTPNotFound)
def notfound_custom(self, request):
    def set_status_code(response):
        # 如果不重新设置状态码,状态码会自动为200
        response.status_code = self.code # pass along 404
    request.after(set_status_code)
    return "My custom not found!"


@App.view(model=User, name='extra')
def erroring(self, request):
    # 抛出异常
    raise HTTPNotFound()

十二、Templates:

from more.chameleon import ChameleonApp

class App(ChameleonApp):
    pass

@App.template_directory()
def get_template_directory():
    return 'templates'

@App.html(model=Person, template='person.pt')
def person_default(self, request):
    return { 'name': self.name }

十三、Configuration:

# 扫描并提交,确保依赖和配置正常
if __name__ == '__main__':
    # morepath.scan(more.jinja2) # scan Jinja2 package
    # morepath.scan() # scan this package
    # 自动扫描
    morepath.autoscan()
    App.commit()

    application = App()
    morepath.run(application)

十四、JSON and validation:

# 设置json相应
class Item(object):
   def __init__(self, value):
       self.value = value

@App.path(model=Item,path="{value}")
def doc_path(value):
    return Item(value)

# 定义实例对象返回的json数据
@App.dump_json(model=Item)
def dump_item_json(self, request):
    return { 'type': 'Item', 'x': self.value }

#在这里直接返回self,后续会自动调用App.dump_item_json
@App.json(model=Item)
def item_default(self, request):
    return self


# 请求数据验证
def my_load(request):
    return request.json

@App.json(model=Item, request_method='POST', load=my_load)
def item_post(self, request, obj):
   # the third obj argument contains the result of my_load(request)
   pass

十五、Settings:

class Sub(App):
   pass
# 设置配置
@Sub.setting(section="logging", name="logfile")
def get_logfile_too():
   return "/a/different/logfile.log"

# 获取设置
app.settings.logging.logfile

# 从配置文件加载配置
import yaml

with open('settings.yml') as config:
     settings_dict = yaml.safe_load(config)

import json

with open('settings.json') as config:
     settings_dict = json.load(config)

# 初始化配置
App.init_settings(settings_dict)
morepath.commit(App)

十六、Logging:

directive_logger = logging.getLogger('morepath.directive')
directive_logger.addHandler(logging.StreamHandler())
directive_logger.setLevel(logging.DEBUG)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值