Для SQLAlchemy существуют интерфейсы управления моделями(что-то типа админки). Как минимум их 2, это Rum и formalchemy.ext.pylons.
Рассмотрим FormAlchemy. Вообще как обычно можно прочитать документацию, но я
опишу еще как это все состыковать с шаблонами на Jinja и поддержкой полей
Postgres таких как MAC, CIDR, NET и т.д..
Создаем контроллер admin:
$ paster controller admin
Далее редактируем его:
# coding=utf-8 import logging from pylons import request, response, session, tmpl_context as c, url from formalchemy.ext.pylons.controller import ModelsController from webhelpers.paginate import Page from repoze.what.predicates import has_permission from repoze.what.plugins.pylonshq import ControllerProtector from myapp.lib.base import BaseController from myapp import model from myapp import forms from myapp.model import meta log = logging.getLogger(__name__) class AdminControllerBase(BaseController): model = model # where your SQLAlchemy mappers are forms = forms # module containing FormAlchemy fieldsets definitions def Session(self): # Session factory return meta.Session ## customize the query for a model listing # def get_page(self): # if self.model_name == 'Foo': # return Page(meta.Session.query(model.Foo).order_by(model.Foo.bar) # return super(AdminControllerBase, self).get_page() AdminController = ModelsController(AdminControllerBase, prefix_name='admin', member_name='model', collection_name='models',)
Дальше добавляем пути:
# ADMIN # Map the /admin url to FA's AdminController # Map static files map.connect('fa_static', '/admin/_static/{path_info:.*}', controller='admin', action='static') # Index page map.connect('admin', '/admin', controller='admin', action='models') map.connect('formatted_admin', '/admin.json', controller='admin', action='models', format='json') # Models map.resource('model', 'models', path_prefix='/admin/{model_name}', controller='admin')
И добавим в шаблоны папку myapp/templates/forms можно взять с github.
Правим следующим образом:
from pylons.templating import render_mako from pylons import config from myapp import model from myapp.lib.base import render from formalchemy import config as fa_config from formalchemy import templates from formalchemy import validators from formalchemy import fields from formalchemy import forms from formalchemy import tables from formalchemy.ext.fsblob import FileFieldRenderer from formalchemy.ext.fsblob import ImageFieldRenderer fa_config.encoding = 'utf-8' class TemplateEngine(templates.TemplateEngine): def render(self, name, **kwargs): return render_mako('/forms/%s.mako' % name, extra_vars=kwargs) fa_config.engine = TemplateEngine() class FieldSet(forms.FieldSet): pass class Grid(tables.Grid): pass ## Initialize fieldsets #Foo = FieldSet(model.Foo) #Reflected = FieldSet(Reflected) ## Initialize grids #FooGrid = Grid(model.Foo) #ReflectedGrid = Grid(Reflected)
Сейчас, как и пишут в документации, вы действительно по адресу
http://localhost:5000/admin попадете в админку! Но только если вы не
используете особенностей БД, например sqlalchemy.databases.postgresql.
Вторая проблема в том что шаблоны админки не встроены в ваши шаблоны.
Для поддержки Postgres полей в FormAlchemy необходимо добавить:
from formalchemy.fields import FieldRenderer from formalchemy.tests import FieldSet from sqlalchemy.databases import postgresql class PostgresFieldRenderer(FieldRenderer): """render a field as a postgres field""" def render(self, **kwargs): return h.text_field(self.name, value=self.value, **kwargs) # fix postgres field in FormAlchemy # tnx for http://code.google.com/p/formalchemy/issues/detail?id=167 FieldSet.default_renderers[postgresql.CIDR] = PostgresFieldRenderer FieldSet.default_renderers[postgresql.MACADDR] = PostgresFieldRenderer FieldSet.default_renderers[postgresql.INET] = PostgresFieldRenderer
Здесь мы создали 3 правила для FormAlchemy как рендерить поля
postgresql.CIDR, postgresql.MACADDR и INET. Этот трюк можно
проделать со всем чем угодно :) Более подробно здесь
http://code.google.com/p/formalchemy/issues/detail?id=167
И наконец встраиваем админку в ваш шаблон.
Для того что бы это сделать придется переписать все шаблоны на jinja и
возможно поменять некоторые файлы (как минимум forms/__init__.py). Я
приведу более ленивый и простой метод. У меня в шаблонах есть header.html
который я инклудом добавляю в base.html в самом начале. Так же и здесь
добавим его в начало админки FormAlchemy.
class BaseController(WSGIController): def __call__(self, environ, start_response): """Invoke the Controller""" # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] # Костыль с mako шаблонами в админке FormAlchemy # FIXME: для чистоты кода, переписать шаблоны с mako на jinja в папке forms c.jinja_menu = render('/common/header.html')
И в шаблоне templates/form/restfieldset.mako
<body> ${c.jinja_menu} <div id="content" class="ui-admin ui-widget"> ... </div> ... </body>
Сразу после <body> добавляем ${c.jinja_menu}. Тем самым в админку уже
отдается отрендеренное меню.
В документации показан интерфейс fa.jquery на самом деле будет обычный. Для
jquery его еще надо дополнительно пилить, добавлять в controller/admin
from fa.jquery.pylons import ModelsController as ModelsControllerJQ и
дальше как сказано в исходниках
https://github.com/FormAlchemy/fa.jquery/blob/master/fa/jquery/pylons.py
обернуть наш контроллер. Что то вроде этого:
AdminController = ModelsController(AdminControllerBase, prefix_name='admin', member_name='model', collection_name='models',) AdminController = ModelsControllerJQ(AdminController, prefix_name='admin', member_name='model', collection_name='models',)
В целом FormAlchemy довольно мощная штука, но очень сильно привязана к mako, поэтому пользоваться ей не удобно и к сожалению придется искать что то другое.