Add grid, CRUD views for Setting model.

This required some tweaks to the base CRUD view etc.
This commit is contained in:
Lance Edgar 2014-11-23 14:27:00 -06:00
parent 86507cf660
commit cc2c2573e5
5 changed files with 205 additions and 32 deletions

View file

@ -1,9 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2012 Lance Edgar # Copyright © 2010-2014 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -21,11 +20,20 @@
# along with Rattail. If not, see <http://www.gnu.org/licenses/>. # along with Rattail. If not, see <http://www.gnu.org/licenses/>.
# #
################################################################################ ################################################################################
""" """
FormAlchemy Grid Classes FormAlchemy Grid Classes
""" """
from __future__ import unicode_literals
from sqlalchemy.orm import object_session
try:
from sqlalchemy.inspection import inspect
except ImportError:
inspect = None
from sqlalchemy.orm import class_mapper
from webhelpers.html import tags from webhelpers.html import tags
from webhelpers.html import HTML from webhelpers.html import HTML
@ -36,7 +44,6 @@ from edbob.util import prettify
from .core import Grid from .core import Grid
from ..db import Session from ..db import Session
from sqlalchemy.orm import object_session
__all__ = ['AlchemyGrid'] __all__ = ['AlchemyGrid']
@ -78,14 +85,18 @@ class AlchemyGrid(Grid):
return HTML.tag('th', class_=class_, field=field.key, return HTML.tag('th', class_=class_, field=field.key,
title=self.column_titles.get(field.key), c=label) title=self.column_titles.get(field.key), c=label)
def view_route_kwargs(self, row): def crud_route_kwargs(self, row):
return {'uuid': row.uuid} if inspect:
mapper = inspect(row.__class__)
else:
mapper = class_mapper(row.__class__)
keys = [k.key for k in mapper.primary_key]
values = [getattr(row, k) for k in keys]
return dict(zip(keys, values))
def edit_route_kwargs(self, row): view_route_kwargs = crud_route_kwargs
return {'uuid': row.uuid} edit_route_kwargs = crud_route_kwargs
delete_route_kwargs = crud_route_kwargs
def delete_route_kwargs(self, row):
return {'uuid': row.uuid}
def iter_fields(self): def iter_fields(self):
return self._formalchemy_grid.render_fields.itervalues() return self._formalchemy_grid.render_fields.itervalues()

View file

@ -0,0 +1,13 @@
## -*- coding: utf-8 -*-
<%inherit file="/crud.mako" />
<%def name="context_menu_items()">
<li>${h.link_to("Back to Settings", url('settings'))}</li>
% if form.readonly:
<li>${h.link_to("Edit this Setting", url('settings.edit', name=form.fieldset.model.name))}</li>
% elif form.updating:
<li>${h.link_to("View this Setting", url('settings.view', name=form.fieldset.model.name))}</li>
% endif
</%def>
${parent.body()}

View file

@ -0,0 +1,12 @@
## -*- coding: utf-8 -*-
<%inherit file="/grid.mako" />
<%def name="title()">Settings</%def>
<%def name="context_menu_items()">
% if request.has_perm('settings.create'):
<li>${h.link_to("Create a new Setting", url('settings.create'))}</li>
% endif
</%def>
${parent.body()}

View file

@ -1,9 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2012 Lance Edgar # Copyright © 2010-2014 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -21,13 +20,21 @@
# along with Rattail. If not, see <http://www.gnu.org/licenses/>. # along with Rattail. If not, see <http://www.gnu.org/licenses/>.
# #
################################################################################ ################################################################################
""" """
CRUD View CRUD View
""" """
from __future__ import unicode_literals
try:
from sqlalchemy.inspection import inspect
except ImportError:
inspect = None
from sqlalchemy.orm import class_mapper
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from .core import View from .core import View
from pyramid.httpexceptions import HTTPFound
from ..forms import AlchemyForm from ..forms import AlchemyForm
from formalchemy import FieldSet from formalchemy import FieldSet
@ -173,33 +180,35 @@ class CrudView(View):
def create(self): def create(self):
return self.crud(self.mapped_class) return self.crud(self.mapped_class)
def get_model_from_request(self):
if inspect:
mapper = inspect(self.mapped_class)
else:
mapper = class_mapper(self.mapped_class)
assert len(mapper.primary_key) == 1
key = self.request.matchdict[mapper.primary_key[0].key]
return self.get_model(key)
def get_model(self, key): def get_model(self, key):
model = Session.query(self.mapped_class).get(key) model = Session.query(self.mapped_class).get(key)
return model return model
def read(self): def read(self):
key = self.request.matchdict['uuid'] model = self.get_model_from_request()
model = self.get_model(key)
if not model: if not model:
return HTTPFound(location=self.home_url) return HTTPNotFound()
return self.crud(model, readonly=True) return self.crud(model, readonly=True)
def update(self): def update(self):
uuid = self.request.matchdict['uuid'] model = self.get_model_from_request()
model = Session.query(self.mapped_class).get(uuid) if uuid else None if not model:
assert model return HTTPNotFound()
return self.crud(model) return self.crud(model)
def pre_delete(self, model):
pass
def post_delete(self, model):
pass
def delete(self): def delete(self):
uuid = self.request.matchdict['uuid'] model = self.get_model_from_request()
model = Session.query(self.mapped_class).get(uuid) if uuid else None if not model:
assert model return HTTPNotFound()
result = self.pre_delete(model) result = self.pre_delete(model)
if result: if result:
return result return result
@ -208,3 +217,9 @@ class CrudView(View):
self.post_delete(model) self.post_delete(model)
self.flash_delete(model) self.flash_delete(model)
return HTTPFound(location=self.home_url) return HTTPFound(location=self.home_url)
def pre_delete(self, model):
pass
def post_delete(self, model):
pass

122
tailbone/views/settings.py Normal file
View file

@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2014 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
# more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Settings Views
"""
from __future__ import unicode_literals
from rattail.db import model
from tailbone.views import SearchableAlchemyGridView, CrudView
class SettingsGrid(SearchableAlchemyGridView):
mapped_class = model.Setting
config_prefix = 'settings'
sort = 'name'
def filter_map(self):
return self.make_filter_map(ilike=['name', 'value'])
def filter_config(self):
return self.make_filter_config(
include_filter_name=True,
filter_type_name='lk',
include_filter_value=True,
filter_type_value='lk')
def sort_map(self):
return self.make_sort_map('name', 'value')
def grid(self):
g = self.make_grid()
g.configure(
include=[
g.name,
g.value,
],
readonly=True)
if self.request.has_perm('settings.view'):
g.viewable = True
g.view_route_name = 'settings.view'
if self.request.has_perm('settings.edit'):
g.editable = True
g.edit_route_name = 'settings.edit'
if self.request.has_perm('settings.delete'):
g.deletable = True
g.delete_route_name = 'settings.delete'
return g
class SettingCrud(CrudView):
mapped_class = model.Setting
home_route = 'settings'
def fieldset(self, model):
fs = self.make_fieldset(model)
fs.configure(
include=[
fs.name,
fs.value,
])
if self.updating:
fs.name.set(readonly=True)
return fs
def add_routes(config):
config.add_route('settings', '/settings')
config.add_route('settings.create', '/settings/new')
config.add_route('settings.view', '/settings/{name}')
config.add_route('settings.edit', '/settings/{name}/edit')
config.add_route('settings.delete', '/settings/{name}/delete')
def includeme(config):
add_routes(config)
# Grid
config.add_view(SettingsGrid,
route_name='settings',
renderer='/settings/index.mako',
permission='settings.list')
# CRUD
config.add_view(SettingCrud, attr='create',
route_name='settings.create',
renderer='/settings/crud.mako',
permission='settings.create')
config.add_view(SettingCrud, attr='read',
route_name='settings.view',
renderer='/settings/crud.mako',
permission='settings.view')
config.add_view(SettingCrud, attr='update',
route_name='settings.edit',
renderer='/settings/crud.mako',
permission='settings.edit')
config.add_view(SettingCrud, attr='delete',
route_name='settings.delete',
permission='settings.delete')