Commit 73b28026 authored by Serge S. Koval's avatar Serge S. Koval

Merge pull request #134 from plaes/expose_plugview

Support for nested flask.views.MethodView
parents 199ccd1f 5c7fbde5
......@@ -7,6 +7,7 @@
---------
.. autofunction:: expose
.. autofunction:: expose_plugview
.. autoclass:: BaseView
:members:
......
from flask import Flask, redirect, render_template, request
from flask.ext import admin
from flask.views import MethodView
class ViewWithMethodViews(admin.BaseView):
@admin.expose('/')
def index(self):
return self.render('methodtest.html')
@admin.expose_plugview('/_api/1')
class API_v1(MethodView):
def get(self, cls):
return cls.render('test.html', request=request, name="API_v1")
def post(self, cls):
return cls.render('test.html', request=request, name="API_v1")
@admin.expose_plugview('/_api/2')
class API_v2(MethodView):
def get(self, cls):
return cls.render('test.html', request=request, name="API_v2")
def post(self, cls):
return cls.render('test.html', request=request, name="API_v2")
# Create flask app
app = Flask(__name__, template_folder='templates')
# Flask views
@app.route('/')
def index():
return redirect('/admin')
if __name__ == '__main__':
# Create admin interface
admin = admin.Admin()
admin.add_view(ViewWithMethodViews())
admin.init_app(app)
# Start app
app.debug = True
app.run()
{% extends 'admin/master.html' %}
{% block body %}
Hello World from MethodTest!<br/>
<form method="POST" action="{{ url_for('.API_v1') }}">
<input type="submit" value="API v1 via POST">
<a href="{{ url_for('.API_v1') }}">v1 via GET</a>
</form>
<form method="POST" action="{{ url_for('.API_v2') }}">
<input type="submit" value="API v2 via POST">
<a href="{{ url_for('.API_v2') }}">v2 via GET</a>
</form>
{% endblock %}
{% extends 'admin/master.html' %}
{% block body %}
This view {{ name }} was accessed using {{ request.method }} request.
<br>
<a href="{{ url_for('.index') }}">Return</a>
{% endblock %}
......@@ -3,4 +3,4 @@ __author__ = 'Serge S. Koval'
__email__ = 'serge.koval+github@gmail.com'
from .base import expose, expose_class, Admin, BaseView, AdminIndexView
from .base import expose, expose_plugview, Admin, BaseView, AdminIndexView
......@@ -22,20 +22,21 @@ def expose(url='/', methods=('GET',)):
f._urls = []
f._urls.append((url, methods))
return f
return wrap
def expose_class(url='/'):
def expose_plugview(url='/'):
"""
User this decorator to expose ``View`` classes (flask.MethodView).
Decorator to expose Flask's pluggable view classes
(``flask.views.View`` or ``flask.views.MethodView``).
:param url:
Relative URL for the view
.. versionadded:: 1.0.4
"""
def wrap(v):
name = v.__name__
return expose(url)(v.as_view(name))
return expose(url, v.methods)(v.as_view(v.__name__))
return wrap
......
{{ request.method }} - {{ name }}
\ No newline at end of file
from nose.tools import ok_, eq_, raises
from flask import Flask
from flask import Flask, request
from flask.views import MethodView
from flask.ext.admin import base
......@@ -29,6 +30,28 @@ class MockView(base.BaseView):
else:
return False
class MockMethodView(base.BaseView):
@base.expose('/')
def index(self):
return 'Success!'
@base.expose_plugview('/_api/1')
class API1(MethodView):
def get(self, cls):
return cls.render('method.html', request=request, name='API1')
def post(self, cls):
return cls.render('method.html', request=request, name='API1')
def put(self, cls):
return cls.render('method.html', request=request, name='API1')
def delete(self, cls):
return cls.render('method.html', request=request, name='API1')
@base.expose_plugview('/_api/2')
class API2(MethodView):
def get(self, cls):
return cls.render('method.html', request=request, name='API2')
def post(self, cls):
return cls.render('method.html', request=request, name='API2')
def test_baseview_defaults():
view = MockView()
......@@ -229,3 +252,30 @@ def test_double_init():
app = Flask(__name__)
admin = base.Admin(app)
admin.init_app(app)
def test_nested_flask_views():
app = Flask(__name__)
admin = base.Admin(app)
view = MockMethodView()
admin.add_view(view)
client = app.test_client()
rv = client.get('/admin/mockmethodview/_api/1')
assert rv.data == 'GET - API1'
rv = client.put('/admin/mockmethodview/_api/1')
assert rv.data == 'PUT - API1'
rv = client.post('/admin/mockmethodview/_api/1')
assert rv.data == 'POST - API1'
rv = client.delete('/admin/mockmethodview/_api/1')
assert rv.data == 'DELETE - API1'
rv = client.get('/admin/mockmethodview/_api/2')
assert rv.data == 'GET - API2'
rv = client.post('/admin/mockmethodview/_api/2')
assert rv.data == 'POST - API2'
rv = client.delete('/admin/mockmethodview/_api/2')
assert rv.status_code == 405
rv = client.put('/admin/mockmethodview/_api/2')
assert rv.status_code == 405
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment