refactor users views etc.
This commit is contained in:
parent
4c2319b759
commit
b3b4e40bcf
9 changed files with 192 additions and 252 deletions
|
@ -13,7 +13,6 @@
|
|||
div.crud {
|
||||
font-size: 10pt;
|
||||
margin: auto;
|
||||
width: 950px;
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +40,7 @@ div.crud div.field-couple {
|
|||
div.crud div.field-couple label {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 135px;
|
||||
width: 140px;
|
||||
font-weight: bold;
|
||||
margin-top: 2px;
|
||||
white-space: nowrap;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
<%def name="title()">People</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<%def name="context_menu_items()">
|
||||
% if request.has_perm('people.create'):
|
||||
<p>${h.link_to("Create a new Person", url('person.new'))}</p>
|
||||
<li>${h.link_to("Create a new Person", url('person.new'))}</li>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
<%def name="title()">Roles</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Create a new Role", url('role.new'))}</p>
|
||||
<%def name="context_menu_items()">
|
||||
<li>${h.link_to("Create a new Role", url('role.new'))}</li>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
<%def name="crud_name()">User</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Back to Users", url('users.list'))}</p>
|
||||
<%def name="context_menu_items()">
|
||||
<li>${h.link_to("Back to Users", url('users.list'))}</li>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
2
edbob/pyramid/templates/users/edit.mako
Normal file
2
edbob/pyramid/templates/users/edit.mako
Normal file
|
@ -0,0 +1,2 @@
|
|||
<%inherit file="/users/crud.mako" />
|
||||
${parent.body()}
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
<%def name="title()">Users</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Create a new User", url('user.new'))}</p>
|
||||
<%def name="context_menu_items()">
|
||||
<li>${h.link_to("Create a new User", url('user.new'))}</li>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
||||
|
|
2
edbob/pyramid/templates/users/new.mako
Normal file
2
edbob/pyramid/templates/users/new.mako
Normal file
|
@ -0,0 +1,2 @@
|
|||
<%inherit file="/users/crud.mako" />
|
||||
${parent.body()}
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
# from pyramid.renderers import render_to_response
|
||||
# from pyramid.httpexceptions import HTTPException, HTTPFound, HTTPOk, HTTPUnauthorized
|
||||
import transaction
|
||||
from pyramid.httpexceptions import HTTPFound, HTTPException
|
||||
# import transaction
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
|
||||
# import sqlahelper
|
||||
|
||||
|
@ -97,6 +97,9 @@ class Crud(object):
|
|||
def post_sync(self, fs):
|
||||
pass
|
||||
|
||||
def validation_failed(self, fs):
|
||||
pass
|
||||
|
||||
def crud(self, obj=None):
|
||||
if obj is None:
|
||||
obj = self.mapped_class
|
||||
|
@ -126,15 +129,14 @@ class Crud(object):
|
|||
|
||||
result = None
|
||||
|
||||
with transaction.manager:
|
||||
fs.sync()
|
||||
result = self.post_sync(fs)
|
||||
if not result:
|
||||
Session.add(fs.model)
|
||||
Session.flush()
|
||||
self.request.session.flash('%s "%s" has been %s.' % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
fs.sync()
|
||||
result = self.post_sync(fs)
|
||||
if not result:
|
||||
Session.add(fs.model)
|
||||
Session.flush()
|
||||
self.request.session.flash('%s "%s" has been %s.' % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
|
||||
if result:
|
||||
return result
|
||||
|
@ -144,6 +146,8 @@ class Crud(object):
|
|||
|
||||
return HTTPFound(location=self.home_url)
|
||||
|
||||
self.validation_failed(fs)
|
||||
|
||||
# TODO: This probably needs attention.
|
||||
if not fs.edit:
|
||||
fs.allow_continue = True
|
||||
|
@ -163,8 +167,7 @@ class Crud(object):
|
|||
uuid = self.request.matchdict['uuid']
|
||||
obj = Session.query(self.mapped_class).get(uuid) if uuid else None
|
||||
assert obj
|
||||
with transaction.manager:
|
||||
Session.delete(obj)
|
||||
Session.delete(obj)
|
||||
return HTTPFound(location=self.home_url)
|
||||
|
||||
@classmethod
|
||||
|
@ -201,109 +204,109 @@ class Crud(object):
|
|||
permission=kw['permission'], http_cache=0)
|
||||
|
||||
|
||||
def crud(request, cls, fieldset_factory, home=None, delete=None, post_sync=None, pre_render=None):
|
||||
"""
|
||||
Adds a common CRUD mechanism for objects.
|
||||
# def crud(request, cls, fieldset_factory, home=None, delete=None, post_sync=None, pre_render=None):
|
||||
# """
|
||||
# Adds a common CRUD mechanism for objects.
|
||||
|
||||
``cls`` should be a SQLAlchemy-mapped class, presumably deriving from
|
||||
:class:`edbob.Object`.
|
||||
# ``cls`` should be a SQLAlchemy-mapped class, presumably deriving from
|
||||
# :class:`edbob.Object`.
|
||||
|
||||
``fieldset_factory`` must be a callable which accepts the fieldset's
|
||||
"model" as its only positional argument.
|
||||
# ``fieldset_factory`` must be a callable which accepts the fieldset's
|
||||
# "model" as its only positional argument.
|
||||
|
||||
``home`` will be used as the redirect location once a form is fully
|
||||
validated and data saved. If you do not speficy this parameter, the
|
||||
user will be redirected to be the CRUD page for the new object (e.g. so
|
||||
an object may be created before certain properties may be edited).
|
||||
# ``home`` will be used as the redirect location once a form is fully
|
||||
# validated and data saved. If you do not speficy this parameter, the
|
||||
# user will be redirected to be the CRUD page for the new object (e.g. so
|
||||
# an object may be created before certain properties may be edited).
|
||||
|
||||
``delete`` may either be a string containing a URL to which the user
|
||||
should be redirected after the object has been deleted, or else a
|
||||
callback which will be executed *instead of* the normal algorithm
|
||||
(which is merely to delete the object via the Session).
|
||||
# ``delete`` may either be a string containing a URL to which the user
|
||||
# should be redirected after the object has been deleted, or else a
|
||||
# callback which will be executed *instead of* the normal algorithm
|
||||
# (which is merely to delete the object via the Session).
|
||||
|
||||
``post_sync`` may be a callback which will be executed immediately
|
||||
after :meth:`FieldSet.sync()` is called, i.e. after validation as well.
|
||||
# ``post_sync`` may be a callback which will be executed immediately
|
||||
# after :meth:`FieldSet.sync()` is called, i.e. after validation as well.
|
||||
|
||||
``pre_render`` may be a callback which will be executed after any POST
|
||||
processing has occured, but just before rendering.
|
||||
"""
|
||||
# ``pre_render`` may be a callback which will be executed after any POST
|
||||
# processing has occured, but just before rendering.
|
||||
# """
|
||||
|
||||
uuid = request.params.get('uuid')
|
||||
obj = Session.query(cls).get(uuid) if uuid else cls
|
||||
assert obj
|
||||
# uuid = request.params.get('uuid')
|
||||
# obj = Session.query(cls).get(uuid) if uuid else cls
|
||||
# assert obj
|
||||
|
||||
if request.params.get('delete'):
|
||||
if delete:
|
||||
if isinstance(delete, basestring):
|
||||
with transaction.manager:
|
||||
Session.delete(obj)
|
||||
return HTTPFound(location=delete)
|
||||
with transaction.manager:
|
||||
res = delete(obj)
|
||||
if res:
|
||||
return res
|
||||
else:
|
||||
with transaction.manager:
|
||||
Session.delete(obj)
|
||||
if not home:
|
||||
raise ValueError("Must specify 'home' or 'delete' url "
|
||||
"in call to crud()")
|
||||
return HTTPFound(location=home)
|
||||
# if request.params.get('delete'):
|
||||
# if delete:
|
||||
# if isinstance(delete, basestring):
|
||||
# with transaction.manager:
|
||||
# Session.delete(obj)
|
||||
# return HTTPFound(location=delete)
|
||||
# with transaction.manager:
|
||||
# res = delete(obj)
|
||||
# if res:
|
||||
# return res
|
||||
# else:
|
||||
# with transaction.manager:
|
||||
# Session.delete(obj)
|
||||
# if not home:
|
||||
# raise ValueError("Must specify 'home' or 'delete' url "
|
||||
# "in call to crud()")
|
||||
# return HTTPFound(location=home)
|
||||
|
||||
fs = fieldset_factory(obj)
|
||||
# fs = fieldset_factory(obj)
|
||||
|
||||
# if not fs.readonly and self.request.params.get('fieldset'):
|
||||
# fs.rebind(data=self.request.params)
|
||||
# if fs.validate():
|
||||
# fs.sync()
|
||||
# if post_sync:
|
||||
# res = post_sync(fs)
|
||||
# if isinstance(res, HTTPFound):
|
||||
# return res
|
||||
# if self.request.params.get('partial'):
|
||||
# self.Session.flush()
|
||||
# return self.json_success(uuid=fs.model.uuid)
|
||||
# return HTTPFound(location=self.request.route_url(objects, action='index'))
|
||||
# # if not fs.readonly and self.request.params.get('fieldset'):
|
||||
# # fs.rebind(data=self.request.params)
|
||||
# # if fs.validate():
|
||||
# # fs.sync()
|
||||
# # if post_sync:
|
||||
# # res = post_sync(fs)
|
||||
# # if isinstance(res, HTTPFound):
|
||||
# # return res
|
||||
# # if self.request.params.get('partial'):
|
||||
# # self.Session.flush()
|
||||
# # return self.json_success(uuid=fs.model.uuid)
|
||||
# # return HTTPFound(location=self.request.route_url(objects, action='index'))
|
||||
|
||||
if not fs.readonly and request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
with transaction.manager:
|
||||
fs.sync()
|
||||
if post_sync:
|
||||
res = post_sync(fs)
|
||||
if res:
|
||||
return res
|
||||
# if not fs.readonly and request.POST:
|
||||
# fs.rebind(data=request.params)
|
||||
# if fs.validate():
|
||||
# with transaction.manager:
|
||||
# fs.sync()
|
||||
# if post_sync:
|
||||
# res = post_sync(fs)
|
||||
# if res:
|
||||
# return res
|
||||
|
||||
if request.params.get('partial'):
|
||||
# Session.flush()
|
||||
# return self.json_success(uuid=fs.model.uuid)
|
||||
assert False, "need to fix this"
|
||||
# if request.params.get('partial'):
|
||||
# # Session.flush()
|
||||
# # return self.json_success(uuid=fs.model.uuid)
|
||||
# assert False, "need to fix this"
|
||||
|
||||
if not home:
|
||||
fs.model = Session.merge(fs.model)
|
||||
home = request.current_route_url(uuid=fs.model.uuid)
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
return HTTPFound(location=home)
|
||||
# if not home:
|
||||
# fs.model = Session.merge(fs.model)
|
||||
# home = request.current_route_url(uuid=fs.model.uuid)
|
||||
# request.session.flash("%s \"%s\" has been %s." % (
|
||||
# fs.crud_title, fs.get_display_text(),
|
||||
# 'updated' if fs.edit else 'created'))
|
||||
# return HTTPFound(location=home)
|
||||
|
||||
data = {'fieldset': fs, 'crud': True}
|
||||
# data = {'fieldset': fs, 'crud': True}
|
||||
|
||||
if pre_render:
|
||||
res = pre_render(fs)
|
||||
if res:
|
||||
if isinstance(res, HTTPException):
|
||||
return res
|
||||
data.update(res)
|
||||
# if pre_render:
|
||||
# res = pre_render(fs)
|
||||
# if res:
|
||||
# if isinstance(res, HTTPException):
|
||||
# return res
|
||||
# data.update(res)
|
||||
|
||||
# data = {'fieldset':fs}
|
||||
# if self.request.params.get('partial'):
|
||||
# return render_to_response('/%s/crud_partial.mako' % objects,
|
||||
# data, request=self.request)
|
||||
# return data
|
||||
# # data = {'fieldset':fs}
|
||||
# # if self.request.params.get('partial'):
|
||||
# # return render_to_response('/%s/crud_partial.mako' % objects,
|
||||
# # data, request=self.request)
|
||||
# # return data
|
||||
|
||||
return data
|
||||
# return data
|
||||
|
||||
|
||||
# class needs_perm(object):
|
||||
|
|
|
@ -26,78 +26,63 @@
|
|||
``edbob.pyramid.views.users`` -- User Views
|
||||
"""
|
||||
|
||||
import transaction
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
from webhelpers.html import literal, tags
|
||||
|
||||
import formalchemy
|
||||
from formalchemy.fields import SelectFieldRenderer
|
||||
from webhelpers.html import literal
|
||||
from webhelpers.html.tags import hidden, link_to, password
|
||||
|
||||
import edbob
|
||||
from edbob.db.auth import set_user_password
|
||||
from edbob.pyramid import filters
|
||||
from edbob.pyramid import forms
|
||||
from edbob.pyramid import grids
|
||||
from edbob.pyramid import Session
|
||||
from edbob.pyramid.filters import filter_ilike
|
||||
from edbob.pyramid.grids import sorter
|
||||
from edbob.pyramid.views import GridView
|
||||
from edbob.pyramid.views.crud import Crud
|
||||
|
||||
|
||||
def filter_map():
|
||||
return filters.get_filter_map(
|
||||
edbob.User,
|
||||
ilike=['username'],
|
||||
person=filters.filter_ilike(edbob.Person.display_name))
|
||||
class UserGrid(GridView):
|
||||
|
||||
def search_config(request, fmap):
|
||||
return filters.get_search_config(
|
||||
'users.list', request, fmap,
|
||||
include_filter_username=True,
|
||||
filter_type_username='lk')
|
||||
mapped_class = edbob.User
|
||||
route_name = 'users.list'
|
||||
route_prefix = 'user'
|
||||
|
||||
def search_form(config):
|
||||
return filters.get_search_form(config)
|
||||
def join_map(self):
|
||||
return {
|
||||
'person':
|
||||
lambda q: q.outerjoin(edbob.Person),
|
||||
}
|
||||
|
||||
def grid_config(request, search, fmap):
|
||||
return grids.get_grid_config(
|
||||
'users.list', request, search,
|
||||
filter_map=fmap, sort='username')
|
||||
def filter_map(self):
|
||||
return self.make_filter_map(
|
||||
ilike=['username'],
|
||||
person=filter_ilike(edbob.Person.display_name))
|
||||
|
||||
def sort_map():
|
||||
return grids.get_sort_map(
|
||||
edbob.User, ['username'],
|
||||
person=grids.sorter(edbob.Person.display_name))
|
||||
def search_config(self, fmap):
|
||||
return self.make_search_config(
|
||||
fmap,
|
||||
include_filter_username=True,
|
||||
filter_type_username='lk',
|
||||
include_filter_person=True,
|
||||
filter_type_person='lk')
|
||||
|
||||
def query(config):
|
||||
jmap = {'person': lambda q: q.outerjoin(edbob.Person)}
|
||||
smap = sort_map()
|
||||
q = Session.query(edbob.User)
|
||||
q = filters.filter_query(q, config, jmap)
|
||||
q = grids.sort_query(q, config, smap, jmap)
|
||||
return q
|
||||
def grid_config(self, search, fmap):
|
||||
return self.make_grid_config(search, fmap,
|
||||
sort='username')
|
||||
|
||||
def sort_map(self):
|
||||
return self.make_sort_map(
|
||||
'username',
|
||||
person=sorter(edbob.Person.display_name))
|
||||
|
||||
def users(context, request):
|
||||
|
||||
fmap = filter_map()
|
||||
config = search_config(request, fmap)
|
||||
search = search_form(config)
|
||||
config = grid_config(request, search, fmap)
|
||||
users = grids.get_pager(query, config)
|
||||
|
||||
g = forms.AlchemyGrid(
|
||||
edbob.User, users, config,
|
||||
gridurl=request.route_url('users.list'),
|
||||
objurl='user.edit')
|
||||
|
||||
g.configure(
|
||||
include=[
|
||||
g.username,
|
||||
g.person,
|
||||
],
|
||||
readonly=True)
|
||||
|
||||
grid = g.render(class_='clickable users')
|
||||
return grids.render_grid(request, grid, search)
|
||||
def grid(self, data, config):
|
||||
g = self.make_grid(data, config)
|
||||
g.configure(
|
||||
include=[
|
||||
g.username,
|
||||
g.person,
|
||||
],
|
||||
readonly=True)
|
||||
return g
|
||||
|
||||
|
||||
class _RolesFieldRenderer(SelectFieldRenderer):
|
||||
|
@ -108,8 +93,8 @@ class _RolesFieldRenderer(SelectFieldRenderer):
|
|||
for uuid in self.value:
|
||||
role = roles.get(uuid)
|
||||
res += literal('<li>%s</li>' % (
|
||||
link_to(role.name,
|
||||
self.request.route_url('role.edit', uuid=role.uuid))))
|
||||
tags.link_to(role.name,
|
||||
self.request.route_url('role.edit', uuid=role.uuid))))
|
||||
res += literal('</ul>')
|
||||
return res
|
||||
|
||||
|
@ -146,8 +131,8 @@ class _ProtectedPersonRenderer(formalchemy.FieldRenderer):
|
|||
|
||||
def render_readonly(self, **kwargs):
|
||||
res = str(self.person)
|
||||
res += hidden('User--person_uuid',
|
||||
value=self.field.parent.person_uuid.value)
|
||||
res += tags.hidden('User--person_uuid',
|
||||
value=self.field.parent.person_uuid.value)
|
||||
return res
|
||||
|
||||
|
||||
|
@ -161,18 +146,19 @@ def ProtectedPersonRenderer(uuid):
|
|||
class _LinkedPersonRenderer(formalchemy.FieldRenderer):
|
||||
|
||||
def render_readonly(self, **kwargs):
|
||||
return link_to(str(self.raw_value),
|
||||
self.request.route_url('person.edit', uuid=self.value))
|
||||
return tags.link_to(str(self.raw_value),
|
||||
self.request.route_url('person.edit', uuid=self.value))
|
||||
|
||||
|
||||
def LinkedPersonRenderer(request):
|
||||
return type('LinkedPersonRenderer', (_LinkedPersonRenderer,), {'request': request})
|
||||
return type('LinkedPersonRenderer', (_LinkedPersonRenderer,),
|
||||
{'request': request})
|
||||
|
||||
|
||||
class PasswordFieldRenderer(formalchemy.PasswordFieldRenderer):
|
||||
|
||||
def render(self, **kwargs):
|
||||
return password(self.name, value='', maxlength=self.length, **kwargs)
|
||||
return tags.password(self.name, value='', maxlength=self.length, **kwargs)
|
||||
|
||||
|
||||
def passwords_match(value, field):
|
||||
|
@ -196,94 +182,42 @@ class PasswordField(formalchemy.Field):
|
|||
set_user_password(self.model, password)
|
||||
|
||||
|
||||
def user_fieldset(user, request):
|
||||
fs = forms.make_fieldset(user, url=request.route_url,
|
||||
url_action=request.current_route_url(),
|
||||
route_name='users.list')
|
||||
class UserCrud(Crud):
|
||||
|
||||
fs.append(PasswordField('password'))
|
||||
fs.append(formalchemy.Field('confirm_password',
|
||||
renderer=PasswordFieldRenderer))
|
||||
mapped_class = edbob.User
|
||||
home_route = 'users.list'
|
||||
|
||||
fs.append(RolesField(
|
||||
'roles', renderer=RolesFieldRenderer(request)))
|
||||
def fieldset(self, user):
|
||||
fs = self.make_fieldset(user)
|
||||
|
||||
fs.configure(
|
||||
include=[
|
||||
fs.person,
|
||||
fs.username,
|
||||
fs.password.label("Set Password"),
|
||||
fs.confirm_password,
|
||||
fs.roles,
|
||||
])
|
||||
fs.append(PasswordField('password'))
|
||||
fs.append(formalchemy.Field('confirm_password',
|
||||
renderer=PasswordFieldRenderer))
|
||||
fs.append(RolesField('roles',
|
||||
renderer=RolesFieldRenderer(self.request)))
|
||||
|
||||
if isinstance(user, edbob.User) and user.person:
|
||||
fs.person.set(readonly=True,
|
||||
renderer=LinkedPersonRenderer(request))
|
||||
fs.configure(
|
||||
include=[
|
||||
fs.username,
|
||||
fs.person,
|
||||
fs.password.label("Set Password"),
|
||||
fs.confirm_password,
|
||||
fs.roles,
|
||||
])
|
||||
|
||||
return fs
|
||||
# if fs.edit and user.person:
|
||||
if isinstance(user, edbob.User) and user.person:
|
||||
fs.person.set(readonly=True,
|
||||
renderer=LinkedPersonRenderer(self.request))
|
||||
|
||||
return fs
|
||||
|
||||
def new_user(request):
|
||||
"""
|
||||
View for creating a new :class:`edbob.User` instance.
|
||||
"""
|
||||
|
||||
fs = user_fieldset(edbob.User, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
Session.add(fs.model)
|
||||
fs.sync()
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('users.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
if fs.person_uuid.value:
|
||||
def validation_failed(self, fs):
|
||||
if not fs.edit and fs.person_uuid.value:
|
||||
fs.person.set(readonly=True,
|
||||
renderer=ProtectedPersonRenderer(fs.person_uuid.value))
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def edit_user(request):
|
||||
uuid = request.matchdict['uuid']
|
||||
user = Session.query(edbob.User).get(uuid) if uuid else None
|
||||
assert user
|
||||
|
||||
fs = user_fieldset(user, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
Session.add(fs.model)
|
||||
fs.sync()
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('users.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
config.add_route('users.list', '/users')
|
||||
config.add_view(users, route_name='users.list', renderer='/users/index.mako',
|
||||
permission='users.list', http_cache=0)
|
||||
|
||||
config.add_route('user.new', '/users/new')
|
||||
config.add_view(new_user, route_name='user.new', renderer='/users/user.mako',
|
||||
permission='users.create', http_cache=0)
|
||||
|
||||
config.add_route('user.edit', '/users/{uuid}/edit')
|
||||
config.add_view(edit_user, route_name='user.edit', renderer='/users/user.mako',
|
||||
permission='users.edit', http_cache=0)
|
||||
UserGrid.add_route(config, 'users.list', '/users')
|
||||
UserCrud.add_routes(config)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue