mirror of
https://github.com/wassname/pyramid_formalchemy.git
synced 2026-06-27 16:10:40 +08:00
Merge branch 'master' of github.com:do3cc/pyramid_formalchemy
This commit is contained in:
+27
-1
@@ -53,7 +53,7 @@ Custom view, factory, forms
|
||||
|
||||
In the toward examples we just pass a ``package`` parameter to
|
||||
:func:`~pyramid_formalchemy.configure`. By default the function will try to
|
||||
load ``package.models`` ``package.models.DBSession`` and ``package.forms`` but
|
||||
load ``package.models``, ``package.models.DBSession`` and ``package.forms`` but
|
||||
you can override this. In this case you don't need to specify a package::
|
||||
|
||||
|
||||
@@ -72,6 +72,32 @@ Having fun with the query_factory parameter
|
||||
.. literalinclude:: ../../formalchemy_project/__init__.py
|
||||
:pyobject: main
|
||||
|
||||
Custom views per model
|
||||
----------------------
|
||||
|
||||
You can also register custom CRUD views per ModelListing::
|
||||
|
||||
|
||||
config.formalchemy_model_view('admin',
|
||||
model='pyramidapp.models.Foo',
|
||||
context='pyramid_formalchemy.resources.ModelListing',
|
||||
renderer='templates/foolisting.pt',
|
||||
attr='listing',
|
||||
request_method='GET',
|
||||
permission='view')
|
||||
|
||||
and per Model::
|
||||
|
||||
|
||||
config.formalchemy_model_view('admin',
|
||||
model='pyramidapp.models.Foo',
|
||||
context='pyramid_formalchemy.resources.Model',
|
||||
name='',
|
||||
renderer='templates/fooshow.pt',
|
||||
attr='show',
|
||||
request_method='GET',
|
||||
permission='view')
|
||||
|
||||
Setting permissions
|
||||
===================
|
||||
|
||||
|
||||
@@ -7,6 +7,30 @@ def includeme(config):
|
||||
config.add_static_view('fa_admin', 'pyramid_formalchemy:static')
|
||||
config.add_directive('formalchemy_admin', 'pyramid_formalchemy.formalchemy_admin')
|
||||
config.add_directive('formalchemy_model', 'pyramid_formalchemy.formalchemy_model')
|
||||
config.add_directive('formalchemy_model_view', 'pyramid_formalchemy.formalchemy_model_view')
|
||||
config.registry.pyramid_formalchemy_views = {}
|
||||
|
||||
def formalchemy_model_view(config, route_name,
|
||||
model=None,
|
||||
name='',
|
||||
view='pyramid_formalchemy.views.ModelView',
|
||||
context='pyramid_formalchemy.resources.Model', **kwargs):
|
||||
"""custom model view registration"""
|
||||
|
||||
model = config.maybe_dotted(model)
|
||||
context = config.maybe_dotted(context)
|
||||
mixin_name = '%sCustom%s_%s_%s' % (model.__name__, context.__name__,
|
||||
route_name, kwargs.get('request_method','GET'))
|
||||
|
||||
factory = type(mixin_name, (context,), {})
|
||||
config.registry.pyramid_formalchemy_views[factory.__name__] = factory
|
||||
|
||||
kw = dict(route_name=route_name, view=view)
|
||||
kw.update(kwargs)
|
||||
|
||||
config.add_view(context=factory,
|
||||
name=name,
|
||||
**kw)
|
||||
|
||||
def formalchemy_model(config, route_name,
|
||||
factory='pyramid_formalchemy.resources.ModelListing',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pyramid.exceptions import NotFound
|
||||
from sqlalchemy import exceptions as sqlalchemy_exceptions
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -74,7 +75,14 @@ class Models(Base):
|
||||
if item in ('json', 'xhr'):
|
||||
self.request.format = item
|
||||
return self
|
||||
model = ModelListing(self.request, item)
|
||||
|
||||
self.request.model_name = item
|
||||
model_class = self.get_model()
|
||||
mixin_name = '%sCustom%s_%s_%s' % (model_class.__name__, ModelListing.__name__,
|
||||
self.request.route_name, self.request.method)
|
||||
mixin = type(mixin_name, (ModelListing, ), {})
|
||||
factory = self.request.registry.pyramid_formalchemy_views.get(mixin.__name__, mixin)
|
||||
model = factory(self.request, item)
|
||||
model.__parent__ = self
|
||||
if hasattr(model, '__acl__'):
|
||||
# propagate permissions to parent
|
||||
@@ -102,9 +110,15 @@ class ModelListing(Base):
|
||||
if item in ('json', 'xhr'):
|
||||
self.request.format = item
|
||||
return self
|
||||
if item in ('new',):
|
||||
|
||||
mixin_name = '%sCustom%s_%s_%s' % (self.request.model_class.__name__, Model.__name__,
|
||||
self.request.route_name, self.request.method)
|
||||
mixin = type(str(mixin_name), (Model, ), {})
|
||||
factory = self.request.registry.pyramid_formalchemy_views.get(mixin.__name__, mixin)
|
||||
try:
|
||||
model = factory(self.request, item)
|
||||
except NotFound:
|
||||
raise KeyError()
|
||||
model = Model(self.request, item)
|
||||
model.__parent__ = self
|
||||
return model
|
||||
|
||||
@@ -116,7 +130,13 @@ class Model(Base):
|
||||
def __init__(self, request, name):
|
||||
Base.__init__(self, request, name)
|
||||
query = request.session_factory.query(request.model_class)
|
||||
request.model_instance = request.query_factory(request, query, id=name)
|
||||
try:
|
||||
request.model_instance = request.query_factory(request, query, id=name)
|
||||
except sqlalchemy_exceptions.SQLAlchemyError, exc:
|
||||
log.exception(exc)
|
||||
request.session_factory().rollback()
|
||||
raise NotFound(request.path)
|
||||
|
||||
if request.model_instance is None:
|
||||
raise NotFound(request.path)
|
||||
request.model_id = name
|
||||
|
||||
@@ -8,6 +8,7 @@ from formalchemy.fields import Field
|
||||
from formalchemy import fatypes
|
||||
from pyramid.renderers import get_renderer
|
||||
from pyramid.response import Response
|
||||
from pyramid.security import has_permission
|
||||
from pyramid import httpexceptions as exc
|
||||
from pyramid.exceptions import NotFound
|
||||
from pyramid_formalchemy.utils import TemplateEngine
|
||||
@@ -55,15 +56,17 @@ class ModelView(object):
|
||||
models = {}
|
||||
if isinstance(request.models, list):
|
||||
for model in request.models:
|
||||
key = model.__name__
|
||||
models[key] = request.fa_url(key, request.format)
|
||||
if has_permission('view', model, request):
|
||||
key = model.__name__
|
||||
models[key] = request.fa_url(key, request.format)
|
||||
else:
|
||||
for key, obj in request.models.__dict__.iteritems():
|
||||
if not key.startswith('_'):
|
||||
if Document is not None:
|
||||
try:
|
||||
if issubclass(obj, Document):
|
||||
models[key] = request.fa_url(key, request.format)
|
||||
if has_permission('view', obj, request):
|
||||
models[key] = request.fa_url(key, request.format)
|
||||
continue
|
||||
except:
|
||||
pass
|
||||
@@ -73,7 +76,8 @@ class ModelView(object):
|
||||
continue
|
||||
if not isinstance(obj, type):
|
||||
continue
|
||||
models[key] = request.fa_url(key, request.format)
|
||||
if has_permission('view', obj, request):
|
||||
models[key] = request.fa_url(key, request.format)
|
||||
if kwargs.get('json'):
|
||||
return models
|
||||
return self.render(models=models)
|
||||
@@ -123,7 +127,7 @@ class ModelView(object):
|
||||
def render_json_format(self, fs=None, **kwargs):
|
||||
request = self.request
|
||||
request.override_renderer = 'json'
|
||||
if fs:
|
||||
if fs is not None:
|
||||
try:
|
||||
fields = fs.jsonify()
|
||||
except AttributeError:
|
||||
|
||||
@@ -22,6 +22,25 @@ def main(global_config, **settings):
|
||||
# register an admin UI for a single model
|
||||
config.formalchemy_model('foo', package='pyramidapp', model='pyramidapp.models.Foo')
|
||||
|
||||
# register custom model listing
|
||||
config.formalchemy_model_view('admin',
|
||||
model='pyramidapp.models.Foo',
|
||||
context='pyramid_formalchemy.resources.ModelListing',
|
||||
renderer='templates/foolisting.pt',
|
||||
attr='listing',
|
||||
request_method='GET',
|
||||
permission='view')
|
||||
|
||||
# register custom model view
|
||||
config.formalchemy_model_view('admin',
|
||||
model='pyramidapp.models.Foo',
|
||||
context='pyramid_formalchemy.resources.Model',
|
||||
name='',
|
||||
renderer='templates/fooshow.pt',
|
||||
attr='show',
|
||||
request_method='GET',
|
||||
permission='view')
|
||||
|
||||
return config.make_wsgi_app()
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from sqlalchemy.orm import scoped_session
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from zope.sqlalchemy import ZopeTransactionExtension
|
||||
from pyramid.security import Allow, ALL_PERMISSIONS
|
||||
from pyramid.security import Allow, Authenticated, ALL_PERMISSIONS
|
||||
|
||||
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
|
||||
Base = declarative_base()
|
||||
@@ -27,6 +27,12 @@ class MyModel(Base):
|
||||
|
||||
class Foo(Base):
|
||||
__tablename__ = 'foo'
|
||||
__acl__ = [
|
||||
(Allow, 'admin', ALL_PERMISSIONS),
|
||||
(Allow, Authenticated, 'view'),
|
||||
(Allow, 'editor', 'edit'),
|
||||
(Allow, 'manager', ('new', 'edit', 'delete')),
|
||||
]
|
||||
id = Column(Integer, primary_key=True)
|
||||
bar = Column(Unicode(255))
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<html metal:use-macro="main.macros['master']">
|
||||
<body>
|
||||
<div metal:fill-slot="main">
|
||||
My Foo custom template
|
||||
<div class="ui-pager" tal:content="structure pager" />
|
||||
<table class="layout-grid" tal:content="structure fs.render()" />
|
||||
<p>
|
||||
<a class="ui-widget-header ui-widget-link ui-corner-all"
|
||||
tal:attributes="href request.fa_url(request.model_name, 'new')">
|
||||
<span class="ui-icon ui-icon-circle-plus"></span>
|
||||
${F_('New')} ${model_name}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<html metal:use-macro="main.macros['master']">
|
||||
<body>
|
||||
<div metal:fill-slot="main">
|
||||
Custom Foo view
|
||||
<div tal:content="structure fs.render()" />
|
||||
<div>
|
||||
<p class="fa_field">
|
||||
<a class="ui-widget-header ui-widget-link ui-widget-button ui-corner-all" href="#"
|
||||
tal:attributes="href request.fa_url(request.model_name, request.model_id, 'edit')">
|
||||
<input type="submit" value="${F_('Edit')}" />
|
||||
</a>
|
||||
<a class="ui-widget-header ui-widget-link ui-corner-all"
|
||||
tal:attributes="href request.fa_url(request.model_name)">
|
||||
<span class="ui-icon ui-icon-circle-arrow-w"></span>
|
||||
${F_('Back')}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user