convenience commit (form refactoring)
This commit is contained in:
		
							parent
							
								
									dd3b42d981
								
							
						
					
					
						commit
						f0c8858fb0
					
				
					 19 changed files with 736 additions and 184 deletions
				
			
		| 
						 | 
				
			
			@ -44,7 +44,7 @@ inited = False
 | 
			
		|||
engines = None
 | 
			
		||||
engine = None
 | 
			
		||||
Session = sessionmaker()
 | 
			
		||||
Base = declarative_base()
 | 
			
		||||
Base = declarative_base(cls=edbob.Object)
 | 
			
		||||
# metadata = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,29 +1,31 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.forms`` -- Forms
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid.forms.formalchemy import *
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.forms`` -- Forms
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid.forms.core import *
 | 
			
		||||
from edbob.pyramid.forms.formalchemy import *
 | 
			
		||||
from edbob.pyramid.forms.simpleform import *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										93
									
								
								edbob/pyramid/forms/core.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								edbob/pyramid/forms/core.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.forms.core`` -- Core Forms
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sqlalchemy.util import OrderedDict
 | 
			
		||||
 | 
			
		||||
from webhelpers.html import literal, tags
 | 
			
		||||
 | 
			
		||||
import edbob
 | 
			
		||||
from edbob.util import requires_impl
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['Form']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Form(edbob.Object):
 | 
			
		||||
    """
 | 
			
		||||
    Generic form class.
 | 
			
		||||
 | 
			
		||||
    This class exists primarily so that rendering calls may mimic those used by
 | 
			
		||||
    FormAlchemy.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    readonly = False
 | 
			
		||||
    successive = False
 | 
			
		||||
 | 
			
		||||
    action_url = None
 | 
			
		||||
    home_route = None
 | 
			
		||||
    home_url = None
 | 
			
		||||
    # template = None
 | 
			
		||||
 | 
			
		||||
    render_fields = OrderedDict()
 | 
			
		||||
    errors = {}
 | 
			
		||||
 | 
			
		||||
    # def __init__(self, request=None, action_url=None, home_url=None, template=None, **kwargs):
 | 
			
		||||
    def __init__(self, request=None, action_url=None, home_url=None, **kwargs):
 | 
			
		||||
        super(Form, self).__init__(**kwargs)
 | 
			
		||||
        self.request = request
 | 
			
		||||
        if action_url:
 | 
			
		||||
            self.action_url = action_url
 | 
			
		||||
        if request and not self.action_url:
 | 
			
		||||
            self.action_url = request.current_route_url()
 | 
			
		||||
        if home_url:
 | 
			
		||||
            self.home_url = home_url
 | 
			
		||||
        if request and not self.home_url:
 | 
			
		||||
            home = self.home_route if self.home_route else 'home'
 | 
			
		||||
            self.home_url = request.route_url(home)
 | 
			
		||||
        # if template:
 | 
			
		||||
        #     self.template = template
 | 
			
		||||
        # if not self.template:
 | 
			
		||||
        #     self.template = '%s.mako' % self.action_url
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def action_url(self):
 | 
			
		||||
        return self.request.current_route_url()
 | 
			
		||||
 | 
			
		||||
    def standard_buttons(self, submit="Save"):
 | 
			
		||||
        return literal(tags.submit('submit', submit) + ' ' + self.cancel_button())
 | 
			
		||||
 | 
			
		||||
    def cancel_button(self):
 | 
			
		||||
        return literal('<button type="button" class="cancel">Cancel</button>')
 | 
			
		||||
 | 
			
		||||
    def render(self, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Renders the form as HTML.  All keyword arguments are passed on to the
 | 
			
		||||
        template context.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        return ''
 | 
			
		||||
| 
						 | 
				
			
			@ -44,12 +44,14 @@ from formalchemy.validators import accepts_none
 | 
			
		|||
import edbob
 | 
			
		||||
from edbob.lib import pretty
 | 
			
		||||
from edbob.util import prettify
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.pyramid import Session, helpers
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid.forms.formalchemy.fieldset import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['AlchemyGrid', 'ChildGridField', 'PropertyField',
 | 
			
		||||
           'EnumFieldRenderer', 'PrettyDateTimeFieldRenderer',
 | 
			
		||||
           'AutocompleteFieldRenderer',
 | 
			
		||||
           'AutocompleteFieldRenderer', 'FieldSet',
 | 
			
		||||
           'make_fieldset', 'required', 'pretty_datetime']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -68,33 +70,6 @@ engine = TemplateEngine()
 | 
			
		|||
formalchemy.config.engine = engine
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FieldSet(formalchemy.FieldSet):
 | 
			
		||||
    """
 | 
			
		||||
    Adds a little magic to the ``FieldSet`` class.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    prettify = staticmethod(prettify)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, model, class_name=None, crud_title=None, url=None,
 | 
			
		||||
                 route_name=None, action_url='', list_url=None, cancel_url=None, **kwargs):
 | 
			
		||||
        super(FieldSet, self).__init__(model, **kwargs)
 | 
			
		||||
        self.class_name = class_name or self._original_cls.__name__.lower()
 | 
			
		||||
        self.crud_title = crud_title or prettify(self.class_name)
 | 
			
		||||
        self.edit = isinstance(model, self._original_cls)
 | 
			
		||||
        self.route_name = route_name or (self.class_name + 's')
 | 
			
		||||
        self.action_url = action_url
 | 
			
		||||
        self.list_url = list_url
 | 
			
		||||
        self.cancel_url = cancel_url or self.list_url
 | 
			
		||||
        self.allow_continue = kwargs.pop('allow_continue', False)
 | 
			
		||||
 | 
			
		||||
    def get_display_text(self):
 | 
			
		||||
        return unicode(self.model)
 | 
			
		||||
 | 
			
		||||
    def render(self, **kwargs):
 | 
			
		||||
        kwargs.setdefault('class_', self.class_name)
 | 
			
		||||
        return formalchemy.FieldSet.render(self, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AlchemyGrid(formalchemy.Grid):
 | 
			
		||||
    """
 | 
			
		||||
    This class defines the basic grid which you see in pretty much all
 | 
			
		||||
| 
						 | 
				
			
			@ -308,11 +283,6 @@ class PropertyField(formalchemy.Field):
 | 
			
		|||
        self.set(readonly=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_fieldset(model, **kwargs):
 | 
			
		||||
    kwargs.setdefault('session', Session())
 | 
			
		||||
    return FieldSet(model, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@accepts_none
 | 
			
		||||
def required(value, field=None):
 | 
			
		||||
    if value is None or value == '':
 | 
			
		||||
| 
						 | 
				
			
			@ -371,6 +341,23 @@ class PrettyDateTimeFieldRenderer(formalchemy.fields.DateTimeFieldRenderer):
 | 
			
		|||
        return pretty_datetime(self.raw_value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DateTimeFieldRenderer(formalchemy.fields.DateTimeFieldRenderer):
 | 
			
		||||
    """
 | 
			
		||||
    Leverages edbob time system to coerce timestamp to local time zone before
 | 
			
		||||
    displaying it.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def render_readonly(self, **kwargs):
 | 
			
		||||
        value = self.raw_value
 | 
			
		||||
        if isinstance(value, datetime.datetime):
 | 
			
		||||
            value = edbob.local_time(value)
 | 
			
		||||
            return value.strftime(self.format)
 | 
			
		||||
        print type(value)
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
FieldSet.default_renderers[formalchemy.types.DateTime] = DateTimeFieldRenderer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def AutocompleteFieldRenderer(service_url, display, width='300px', callback=None, **kwargs):
 | 
			
		||||
    """
 | 
			
		||||
    Returns a field renderer class which leverages jQuery autocomplete to
 | 
			
		||||
| 
						 | 
				
			
			@ -421,7 +408,6 @@ class _AutocompleteFieldRenderer(fields.FieldRenderer):
 | 
			
		|||
        autocompleter_name = 'autocompleter_%s' % self.name.replace('-', '_')
 | 
			
		||||
        return formalchemy.config.engine('field_autocomplete', fieldname=self.name,
 | 
			
		||||
                                         fieldvalue=self.value, display=self._display(self.value),
 | 
			
		||||
                                         autocompleter_name=autocompleter_name,
 | 
			
		||||
                                         autocompleter=autocompleter_name,
 | 
			
		||||
                                         service_url=self.service_url, width=self.width,
 | 
			
		||||
                                         callback=self.callback, hidden=tags.hidden, text=tags.text,
 | 
			
		||||
                                         **kwargs)
 | 
			
		||||
                                         callback=self.callback, h=helpers, **kwargs)
 | 
			
		||||
							
								
								
									
										72
									
								
								edbob/pyramid/forms/formalchemy/fieldset.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								edbob/pyramid/forms/formalchemy/fieldset.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.forms.formalchemy.fieldset`` -- FormAlchemy FieldSet
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import formalchemy
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.util import prettify
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['FieldSet', 'make_fieldset']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FieldSet(formalchemy.FieldSet):
 | 
			
		||||
    """
 | 
			
		||||
    Adds a little magic to the :class:`formalchemy.FieldSet` class.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    prettify = staticmethod(prettify)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, model, class_name=None, crud_title=None, url=None,
 | 
			
		||||
                 route_name=None, action_url='', home_url=None, **kwargs):
 | 
			
		||||
        super(FieldSet, self).__init__(model, **kwargs)
 | 
			
		||||
        self.class_name = class_name or self._original_cls.__name__.lower()
 | 
			
		||||
        self.crud_title = crud_title or prettify(self.class_name)
 | 
			
		||||
        self.edit = isinstance(model, self._original_cls)
 | 
			
		||||
        self.route_name = route_name or (self.class_name + 's')
 | 
			
		||||
        self.action_url = action_url
 | 
			
		||||
        self.home_url = home_url
 | 
			
		||||
        self.allow_continue = kwargs.pop('allow_continue', False)
 | 
			
		||||
 | 
			
		||||
    def get_display_text(self):
 | 
			
		||||
        return unicode(self.model)
 | 
			
		||||
 | 
			
		||||
    def render(self, **kwargs):
 | 
			
		||||
        kwargs.setdefault('class_', self.class_name)
 | 
			
		||||
        return super(FieldSet, self).render(**kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def make_fieldset(model, **kwargs):
 | 
			
		||||
    """
 | 
			
		||||
    Returns a :class:`FieldSet` equipped with the current scoped
 | 
			
		||||
    :class:`edbob.db.Session` instance (unless ``session`` is provided as a
 | 
			
		||||
    keyword argument).
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    kwargs.setdefault('session', Session())
 | 
			
		||||
    return FieldSet(model, **kwargs)
 | 
			
		||||
							
								
								
									
										53
									
								
								edbob/pyramid/forms/simpleform.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								edbob/pyramid/forms/simpleform.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.forms.simpleform`` -- pyramid_simpleform Forms
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import pyramid_simpleform
 | 
			
		||||
from pyramid.renderers import render
 | 
			
		||||
from pyramid_simpleform.renderers import FormRenderer
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid import helpers
 | 
			
		||||
from edbob.pyramid.forms import Form
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['SimpleForm']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SimpleForm(Form):
 | 
			
		||||
 | 
			
		||||
    template = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request, **kwargs):
 | 
			
		||||
        super(SimpleForm, self).__init__(request, **kwargs)
 | 
			
		||||
        self.form = pyramid_simpleform.Form(request)
 | 
			
		||||
 | 
			
		||||
    def render(self, **kwargs):
 | 
			
		||||
        kw = {
 | 
			
		||||
            'form': self,
 | 
			
		||||
            }
 | 
			
		||||
        kw.update(kwargs)
 | 
			
		||||
        return render('/forms/form.mako', kw)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,8 @@
 | 
			
		|||
<%def name="global_title()">edbob</%def>
 | 
			
		||||
<%def name="title()">${(fieldset.crud_title+' : '+fieldset.get_display_text() if fieldset.edit else 'New '+fieldset.crud_title) if crud else ''}</%def>
 | 
			
		||||
<%def name="title()"></%def>
 | 
			
		||||
<%def name="head_tags()"></%def>
 | 
			
		||||
<%def name="home_link()"><h1 class="right">${h.link_to("Home", url('home'))}</h1></%def>
 | 
			
		||||
<%def name="menu()"></%def>
 | 
			
		||||
<%def name="footer()">
 | 
			
		||||
  powered by ${h.link_to('edbob', 'http://edbob.org', target='_blank')} v${edbob.__version__}
 | 
			
		||||
</%def>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
<%inherit file="/base.mako" />
 | 
			
		||||
 | 
			
		||||
<%def name="title()">${(fieldset.crud_title+' : '+fieldset.get_display_text() if fieldset.edit else 'New '+fieldset.crud_title) if crud else ''}</%def>
 | 
			
		||||
 | 
			
		||||
<div class="crud wrapper">
 | 
			
		||||
 | 
			
		||||
  <div class="right">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								edbob/pyramid/templates/edbob/form.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								edbob/pyramid/templates/edbob/form.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
<%inherit file="/base.mako" />
 | 
			
		||||
 | 
			
		||||
<%def name="buttons()"></%def>
 | 
			
		||||
 | 
			
		||||
<div class="wrapper">
 | 
			
		||||
 | 
			
		||||
  <div class="right">
 | 
			
		||||
    ${self.menu()}
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="left">
 | 
			
		||||
    <% print 'type (2) is', type(form) %>
 | 
			
		||||
    ${form.render(buttons=self.buttons)|n}
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										58
									
								
								edbob/pyramid/templates/edbob/form_body.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								edbob/pyramid/templates/edbob/form_body.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
<% _focus_rendered = False %>
 | 
			
		||||
 | 
			
		||||
<div class="form">
 | 
			
		||||
  ${h.form(form.action_url, enctype='multipart/form-data')}
 | 
			
		||||
 | 
			
		||||
  % for error in form.errors.get(None, []):
 | 
			
		||||
      <div class="fieldset-error">${error}</div>
 | 
			
		||||
  % endfor
 | 
			
		||||
 | 
			
		||||
  % for field in form.render_fields.itervalues():
 | 
			
		||||
 | 
			
		||||
      <div class="field-couple ${field.name}">
 | 
			
		||||
        % for error in field.errors:
 | 
			
		||||
            <div class="field-error">${error}</div>
 | 
			
		||||
        % endfor
 | 
			
		||||
        ${field.label_tag()|n}
 | 
			
		||||
        <div class="field">
 | 
			
		||||
          ${field.render()|n}
 | 
			
		||||
        </div>
 | 
			
		||||
        % if 'instructions' in field.metadata:
 | 
			
		||||
            <span class="instructions">${field.metadata['instructions']}</span>
 | 
			
		||||
        % endif
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      % if (form.focus == field or form.focus is True) and not _focus_rendered:
 | 
			
		||||
          % if not field.is_readonly():
 | 
			
		||||
              <script language="javascript" type="text/javascript">
 | 
			
		||||
                $(function() {
 | 
			
		||||
                    $('#${field.renderer.name}').focus();
 | 
			
		||||
                });
 | 
			
		||||
              </script>
 | 
			
		||||
              <% _focus_rendered = True %>
 | 
			
		||||
          % endif
 | 
			
		||||
      % endif
 | 
			
		||||
 | 
			
		||||
  % endfor
 | 
			
		||||
 | 
			
		||||
  % if form.successive:
 | 
			
		||||
      <div class="checkbox">
 | 
			
		||||
        ${h.checkbox('keep-going', checked=True)}
 | 
			
		||||
        <label for="keep-going">Add another after this one</label>
 | 
			
		||||
      </div>
 | 
			
		||||
  % endif
 | 
			
		||||
 | 
			
		||||
  <div class="buttons">
 | 
			
		||||
    ${h.submit('submit', "Save")}
 | 
			
		||||
    <button type="button" class="cancel">Cancel</button>
 | 
			
		||||
  </div>
 | 
			
		||||
  ${h.end_form()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script language="javascript" type="text/javascript">
 | 
			
		||||
  $(function() {
 | 
			
		||||
      $('button.cancel').click(function() {
 | 
			
		||||
          location.href = '${form.home_url}';
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -40,21 +40,21 @@ ${h.image(logo_url, "${self.global_title()} logo", id='login-logo', **logo_kwarg
 | 
			
		|||
$(function() {
 | 
			
		||||
 | 
			
		||||
    $('form').submit(function() {
 | 
			
		||||
	if (! $('#username').val()) {
 | 
			
		||||
	    with ($('#username').get(0)) {
 | 
			
		||||
		select();
 | 
			
		||||
		focus();
 | 
			
		||||
	    }
 | 
			
		||||
	    return false;
 | 
			
		||||
	}
 | 
			
		||||
	if (! $('#password').val()) {
 | 
			
		||||
	    with ($('#password').get(0)) {
 | 
			
		||||
		select();
 | 
			
		||||
		focus();
 | 
			
		||||
	    }
 | 
			
		||||
	    return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
        if (! $('#username').val()) {
 | 
			
		||||
            with ($('#username').get(0)) {
 | 
			
		||||
            select();
 | 
			
		||||
            focus();
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (! $('#password').val()) {
 | 
			
		||||
            with ($('#password').get(0)) {
 | 
			
		||||
            select();
 | 
			
		||||
            focus();
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('#username').focus();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								edbob/pyramid/templates/form.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								edbob/pyramid/templates/form.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
<%inherit file="/edbob/form.mako" />
 | 
			
		||||
${parent.body()}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<div id="${fieldname}-container" class="autocomplete-container">
 | 
			
		||||
  ${hidden(fieldname, id=fieldname, value=fieldvalue)}
 | 
			
		||||
  ${text(fieldname+'-textbox', id=fieldname+'-textbox', value=display,
 | 
			
		||||
  ${h.hidden(fieldname, id=fieldname, value=fieldvalue)}
 | 
			
		||||
  ${h.text(fieldname+'-textbox', id=fieldname+'-textbox', value=display,
 | 
			
		||||
      class_='autocomplete-textbox', style='display: none;' if fieldvalue else '')}
 | 
			
		||||
  <div id="${fieldname}-display" class="autocomplete-display"${'' if fieldvalue else ' style="display: none;"'|n}>
 | 
			
		||||
    <span>${display}</span>
 | 
			
		||||
| 
						 | 
				
			
			@ -9,18 +9,18 @@
 | 
			
		|||
</div>
 | 
			
		||||
<script language="javascript" type="text/javascript">
 | 
			
		||||
$(function() {
 | 
			
		||||
    var ${autocompleter_name} = $('#${fieldname}-textbox').autocomplete({
 | 
			
		||||
	serviceUrl: '${service_url}',
 | 
			
		||||
	width: '${width}',
 | 
			
		||||
	onSelect: function(value, data) {
 | 
			
		||||
            $('#${fieldname}').val(data);
 | 
			
		||||
            $('#${fieldname}-display span').text(value);
 | 
			
		||||
            $('#${fieldname}-textbox').hide();
 | 
			
		||||
            $('#${fieldname}-display').show();
 | 
			
		||||
	    % if callback:
 | 
			
		||||
	        ${callback}(value, data);
 | 
			
		||||
	    % endif
 | 
			
		||||
	},
 | 
			
		||||
    var ${autocompleter} = $('#${fieldname}-textbox').autocomplete({
 | 
			
		||||
    serviceUrl: '${service_url}',
 | 
			
		||||
    width: '${width}',
 | 
			
		||||
    onSelect: function(value, data) {
 | 
			
		||||
        $('#${fieldname}').val(data);
 | 
			
		||||
        $('#${fieldname}-display span').text(value);
 | 
			
		||||
        $('#${fieldname}-textbox').hide();
 | 
			
		||||
        $('#${fieldname}-display').show();
 | 
			
		||||
        % if callback:
 | 
			
		||||
            ${callback}(value, data);
 | 
			
		||||
        % endif
 | 
			
		||||
    },
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,7 +52,7 @@
 | 
			
		|||
<script language="javascript" type="text/javascript">
 | 
			
		||||
  $(function() {
 | 
			
		||||
      $('button.cancel').click(function() {
 | 
			
		||||
          location.href = '${fieldset.cancel_url}';
 | 
			
		||||
          location.href = '${fieldset.home_url}';
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										62
									
								
								edbob/pyramid/templates/forms/form.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								edbob/pyramid/templates/forms/form.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
<% _focus_rendered = False %>
 | 
			
		||||
 | 
			
		||||
<div class="form">
 | 
			
		||||
  ${h.form(form.action_url, enctype='multipart/form-data')}
 | 
			
		||||
 | 
			
		||||
  % for error in form.errors.get(None, []):
 | 
			
		||||
      <div class="fieldset-error">${error}</div>
 | 
			
		||||
  % endfor
 | 
			
		||||
 | 
			
		||||
  % for field in form.render_fields.itervalues():
 | 
			
		||||
 | 
			
		||||
      <div class="field-couple ${field.name}">
 | 
			
		||||
        % for error in field.errors:
 | 
			
		||||
            <div class="field-error">${error}</div>
 | 
			
		||||
        % endfor
 | 
			
		||||
        ${field.label_tag()|n}
 | 
			
		||||
        <div class="field">
 | 
			
		||||
          ${field.render()|n}
 | 
			
		||||
        </div>
 | 
			
		||||
        % if 'instructions' in field.metadata:
 | 
			
		||||
            <span class="instructions">${field.metadata['instructions']}</span>
 | 
			
		||||
        % endif
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      % if (form.focus == field or form.focus is True) and not _focus_rendered:
 | 
			
		||||
          % if not field.is_readonly():
 | 
			
		||||
              <script language="javascript" type="text/javascript">
 | 
			
		||||
                $(function() {
 | 
			
		||||
                    $('#${field.renderer.name}').focus();
 | 
			
		||||
                });
 | 
			
		||||
              </script>
 | 
			
		||||
              <% _focus_rendered = True %>
 | 
			
		||||
          % endif
 | 
			
		||||
      % endif
 | 
			
		||||
 | 
			
		||||
  % endfor
 | 
			
		||||
 | 
			
		||||
  % if form.successive:
 | 
			
		||||
      <div class="checkbox">
 | 
			
		||||
        ${h.checkbox('keep-going', checked=True)}
 | 
			
		||||
        <label for="keep-going">Add another after this one</label>
 | 
			
		||||
      </div>
 | 
			
		||||
  % endif
 | 
			
		||||
 | 
			
		||||
  <div class="buttons">
 | 
			
		||||
    % if buttons:
 | 
			
		||||
        ${capture(buttons)}
 | 
			
		||||
    % else:
 | 
			
		||||
        ${h.submit('submit', "Save")}
 | 
			
		||||
        <button type="button" class="cancel">Cancel</button>
 | 
			
		||||
    % endif
 | 
			
		||||
  </div>
 | 
			
		||||
  ${h.end_form()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script language="javascript" type="text/javascript">
 | 
			
		||||
  $(function() {
 | 
			
		||||
      $('button.cancel').click(function() {
 | 
			
		||||
          location.href = '${form.home_url}';
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -27,67 +27,15 @@
 | 
			
		|||
"""
 | 
			
		||||
 | 
			
		||||
from pyramid.httpexceptions import HTTPFound
 | 
			
		||||
from pyramid.renderers import render_to_response
 | 
			
		||||
from pyramid.security import authenticated_userid
 | 
			
		||||
 | 
			
		||||
from webhelpers.html import literal
 | 
			
		||||
from webhelpers.html.tags import link_to
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.pyramid.forms.formalchemy import AutocompleteFieldRenderer
 | 
			
		||||
from edbob.util import requires_impl
 | 
			
		||||
from edbob.pyramid.views.autocomplete import *
 | 
			
		||||
from edbob.pyramid.views.form import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Autocomplete(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request):
 | 
			
		||||
        self.request = request
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def mapped_class(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def fieldname(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def route_name(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        query = self.request.params['query']
 | 
			
		||||
        q = Session.query(self.mapped_class)
 | 
			
		||||
        q = q.filter(getattr(self.mapped_class, self.fieldname).ilike('%%%s%%' % query))
 | 
			
		||||
        objs = q.order_by(getattr(self.mapped_class, self.fieldname)).all()
 | 
			
		||||
        data = dict(
 | 
			
		||||
            query=query,
 | 
			
		||||
            suggestions=[getattr(x, self.fieldname) for x in objs],
 | 
			
		||||
            data=[x.uuid for x in objs],
 | 
			
		||||
            )
 | 
			
		||||
        response = render_to_response('json', data, request=self.request)
 | 
			
		||||
        response.headers['Content-Type'] = 'application/json'
 | 
			
		||||
        return response
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def add_route(cls, config, url):
 | 
			
		||||
    # def add_routes(cls, config, route_prefix, url_prefix, template_prefix=None, permission_prefix=None):
 | 
			
		||||
        """
 | 
			
		||||
        Add 'autocomplete' route to the config object.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        config.add_route(cls.route_name, url)
 | 
			
		||||
        config.add_view(cls, route_name=cls.route_name, http_cache=0)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def renderer(cls, request):
 | 
			
		||||
        return AutocompleteFieldRenderer(request.route_url(cls.route_name),
 | 
			
		||||
                                         (cls.mapped_class, cls.fieldname))
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
def forbidden(request):
 | 
			
		||||
    """
 | 
			
		||||
    The forbidden view.  This is triggered whenever access rights are denied
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										105
									
								
								edbob/pyramid/views/autocomplete.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								edbob/pyramid/views/autocomplete.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.views.autocomplete`` -- Autocomplete View
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from pyramid.renderers import render_to_response
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.pyramid.forms.formalchemy import AutocompleteFieldRenderer
 | 
			
		||||
from edbob.util import requires_impl
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['Autocomplete']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Autocomplete(object):
 | 
			
		||||
 | 
			
		||||
    route = None
 | 
			
		||||
    url = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request):
 | 
			
		||||
        self.request = request
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def mapped_class(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def fieldname(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_route(cls):
 | 
			
		||||
        if not cls.route:
 | 
			
		||||
            name = cls.mapped_class.__name__.lower()
 | 
			
		||||
            cls.route = '%ss.autocomplete' % name
 | 
			
		||||
        return cls.route
 | 
			
		||||
 | 
			
		||||
    def filter_query(self, q):
 | 
			
		||||
        return q
 | 
			
		||||
 | 
			
		||||
    def make_query(self, query):
 | 
			
		||||
        q = Session.query(self.mapped_class)
 | 
			
		||||
        q = self.filter_query(q)
 | 
			
		||||
        q = q.filter(getattr(self.mapped_class, self.fieldname).ilike('%%%s%%' % query))
 | 
			
		||||
        q = q.order_by(getattr(self.mapped_class, self.fieldname))
 | 
			
		||||
        return q
 | 
			
		||||
 | 
			
		||||
    def query(self, query):
 | 
			
		||||
        return self.make_query(query)
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        query = self.request.params['query']
 | 
			
		||||
        objs = self.query(query).all()
 | 
			
		||||
        data = dict(
 | 
			
		||||
            query=query,
 | 
			
		||||
            suggestions=[getattr(x, self.fieldname) for x in objs],
 | 
			
		||||
            data=[x.uuid for x in objs],
 | 
			
		||||
            )
 | 
			
		||||
        response = render_to_response('json', data, request=self.request)
 | 
			
		||||
        response.headers['Content-Type'] = 'application/json'
 | 
			
		||||
        return response
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def add_route(cls, config):
 | 
			
		||||
        """
 | 
			
		||||
        Add 'autocomplete' route to the config object.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        name = cls.mapped_class.__name__.lower()
 | 
			
		||||
        route = cls.get_route()
 | 
			
		||||
        url = cls.url or '/%ss/autocomplete' % name
 | 
			
		||||
 | 
			
		||||
        config.add_route(route, url)
 | 
			
		||||
        config.add_view(cls, route_name=route, http_cache=0)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def renderer(cls, request):
 | 
			
		||||
        return AutocompleteFieldRenderer(request.route_url(cls.get_route()),
 | 
			
		||||
                                         (cls.mapped_class, cls.fieldname))
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ from pyramid.httpexceptions import HTTPFound, HTTPException
 | 
			
		|||
# from rattail.db.perms import has_permission
 | 
			
		||||
# from rattail.pyramid.forms.formalchemy import Grid
 | 
			
		||||
 | 
			
		||||
import edbob
 | 
			
		||||
from edbob.db import Base
 | 
			
		||||
from edbob.pyramid import forms
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
| 
						 | 
				
			
			@ -45,28 +46,42 @@ from edbob.util import requires_impl
 | 
			
		|||
 | 
			
		||||
class Crud(object):
 | 
			
		||||
 | 
			
		||||
    routes = ['new', 'edit', 'delete']
 | 
			
		||||
 | 
			
		||||
    route_prefix = None
 | 
			
		||||
    url_prefix = None
 | 
			
		||||
    template_prefix = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request):
 | 
			
		||||
        self.request = request
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def mapped_class(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
    def list_route(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
    def home_route(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def list_url(self):
 | 
			
		||||
        return self.request.route_url(self.list_route)
 | 
			
		||||
    def home_url(self):
 | 
			
		||||
        return self.request.route_url(self.home_route)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def cancel_route(self):
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def permission_prefix(self):
 | 
			
		||||
        return self.route_prefix + 's'
 | 
			
		||||
 | 
			
		||||
    def make_fieldset(self, model, **kwargs):
 | 
			
		||||
        if 'action_url' not in kwargs:
 | 
			
		||||
            kwargs['action_url'] = self.request.current_route_url()
 | 
			
		||||
        if 'list_url' not in kwargs:
 | 
			
		||||
            kwargs['list_url'] = self.list_url
 | 
			
		||||
        if 'home_url' not in kwargs:
 | 
			
		||||
            kwargs['home_url'] = self.home_url
 | 
			
		||||
        return forms.make_fieldset(model, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def fieldset(self, obj):
 | 
			
		||||
| 
						 | 
				
			
			@ -80,25 +95,55 @@ class Crud(object):
 | 
			
		|||
        fs = self.make_fieldset(obj)
 | 
			
		||||
        return fs
 | 
			
		||||
 | 
			
		||||
    def crud(self, obj):
 | 
			
		||||
    def post_sync(self, fs):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def crud(self, obj=None):
 | 
			
		||||
        if obj is None:
 | 
			
		||||
            obj = self.mapped_class
 | 
			
		||||
 | 
			
		||||
        # fs = self.fieldset(obj)
 | 
			
		||||
        # if not fs.readonly and self.request.POST:
 | 
			
		||||
        #     fs.rebind(data=self.request.params)
 | 
			
		||||
        #     if fs.validate():
 | 
			
		||||
 | 
			
		||||
        #         with transaction.manager:
 | 
			
		||||
        #             fs.sync()
 | 
			
		||||
        #             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 self.request.params.get('add-another') == '1':
 | 
			
		||||
        #             return HTTPFound(location=self.request.current_route_url())
 | 
			
		||||
 | 
			
		||||
        #         return HTTPFound(location=self.home_url)
 | 
			
		||||
 | 
			
		||||
        fs = self.fieldset(obj)
 | 
			
		||||
        if not fs.readonly and self.request.POST:
 | 
			
		||||
            fs.rebind(data=self.request.params)
 | 
			
		||||
            if fs.validate():
 | 
			
		||||
 | 
			
		||||
                result = None
 | 
			
		||||
 | 
			
		||||
                with transaction.manager:
 | 
			
		||||
                    fs.sync()
 | 
			
		||||
                    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'))
 | 
			
		||||
                    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
 | 
			
		||||
 | 
			
		||||
                if self.request.params.get('add-another') == '1':
 | 
			
		||||
                    return HTTPFound(location=self.request.current_route_url())
 | 
			
		||||
 | 
			
		||||
                return HTTPFound(location=self.list_url)
 | 
			
		||||
                return HTTPFound(location=self.home_url)
 | 
			
		||||
 | 
			
		||||
        # TODO: This probably needs attention.
 | 
			
		||||
        if not fs.edit:
 | 
			
		||||
| 
						 | 
				
			
			@ -121,31 +166,40 @@ class Crud(object):
 | 
			
		|||
        assert obj
 | 
			
		||||
        with transaction.manager:
 | 
			
		||||
            Session.delete(obj)
 | 
			
		||||
        return HTTPFound(location=self.request.route_url(self.list_route))
 | 
			
		||||
        return HTTPFound(location=self.home_url)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def add_routes(cls, config, route_prefix, url_prefix, template_prefix=None, permission_prefix=None):
 | 
			
		||||
    def add_routes(cls, config):
 | 
			
		||||
        """
 | 
			
		||||
        Add standard routes (i.e. 'new', 'edit' and 'delete') for the mapped
 | 
			
		||||
        class to the config object.
 | 
			
		||||
        Add routes to the config object.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if not template_prefix:
 | 
			
		||||
            template_prefix = url_prefix
 | 
			
		||||
        if not permission_prefix:
 | 
			
		||||
            permission_prefix = route_prefix + 's'
 | 
			
		||||
        routes = cls.routes
 | 
			
		||||
        if isinstance(routes, list):
 | 
			
		||||
            _routes = routes
 | 
			
		||||
            routes = {}
 | 
			
		||||
            for route in _routes:
 | 
			
		||||
                routes[route] = {}
 | 
			
		||||
 | 
			
		||||
        config.add_route('%s.new' % route_prefix, '%s/new' % url_prefix)
 | 
			
		||||
        config.add_view(cls, attr='new', route_name='%s.new' % route_prefix, renderer='%s/crud.mako' % template_prefix,
 | 
			
		||||
                        permission='%s.create' % permission_prefix, http_cache=0)
 | 
			
		||||
        route_prefix = cls.route_prefix or cls.mapped_class.__name__.lower()
 | 
			
		||||
        url_prefix = cls.url_prefix or '/%ss' % route_prefix
 | 
			
		||||
        template_prefix = cls.template_prefix or url_prefix
 | 
			
		||||
        permission_prefix = cls.permission_prefix or '%ss' % route_prefix
 | 
			
		||||
 | 
			
		||||
        config.add_route('%s.edit' % route_prefix, '%s/{uuid}/edit' % url_prefix)
 | 
			
		||||
        config.add_view(cls, attr='edit', route_name='%s.edit' % route_prefix, renderer='%s/crud.mako' % template_prefix,
 | 
			
		||||
                        permission='%s.edit' % permission_prefix, http_cache=0)
 | 
			
		||||
 | 
			
		||||
        config.add_route('%s.delete' % route_prefix, '%s/{uuid}/delete' % url_prefix)
 | 
			
		||||
        config.add_view(cls, attr='delete', route_name='%s.delete' % route_prefix,
 | 
			
		||||
                        permission='%s.delete' % permission_prefix, http_cache=0)
 | 
			
		||||
        for action in routes:
 | 
			
		||||
            kw = dict(
 | 
			
		||||
                route='%s.%s' % (route_prefix, action),
 | 
			
		||||
                renderer='%s/%s.mako' % (template_prefix, action),
 | 
			
		||||
                permission='%s.%s' % (permission_prefix, dict(new='create').get(action, action)),
 | 
			
		||||
                )
 | 
			
		||||
            if action == 'new':
 | 
			
		||||
                kw['url'] = '%s/new' % url_prefix
 | 
			
		||||
            else:
 | 
			
		||||
                kw['url'] = '%s/{uuid}/%s' % (url_prefix, action)
 | 
			
		||||
            kw.update(routes[action])
 | 
			
		||||
            config.add_route(kw['route'], kw['url'])
 | 
			
		||||
            config.add_view(cls, attr=action, route_name=kw['route'], renderer=kw['renderer'],
 | 
			
		||||
                            permission=kw['permission'], http_cache=0)
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
def crud(request, cls, fieldset_factory, home=None, delete=None, post_sync=None, pre_render=None):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										98
									
								
								edbob/pyramid/views/form.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								edbob/pyramid/views/form.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8  -*-
 | 
			
		||||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  edbob -- Pythonic Software Framework
 | 
			
		||||
#  Copyright © 2010-2012 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of edbob.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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.
 | 
			
		||||
#
 | 
			
		||||
#  edbob 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 edbob.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
################################################################################
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
``edbob.pyramid.views.form`` -- Generic Form View
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import transaction
 | 
			
		||||
from pyramid.httpexceptions import HTTPFound
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.pyramid.forms import SimpleForm
 | 
			
		||||
from edbob.util import requires_impl
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ['FormView']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FormView(object):
 | 
			
		||||
    """
 | 
			
		||||
    This view provides basic form processing goodies.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    route = None
 | 
			
		||||
    url = None
 | 
			
		||||
    template = None
 | 
			
		||||
    permission = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request):
 | 
			
		||||
        self.request = request
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        """
 | 
			
		||||
        Callable for the view.  This method creates the underlying form and
 | 
			
		||||
        processes data if any was submitted.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        f = self.form(self.request)
 | 
			
		||||
        if not f.readonly and self.request.POST:
 | 
			
		||||
            f.rebind(data=self.request.params)
 | 
			
		||||
            if f.validate():
 | 
			
		||||
 | 
			
		||||
                with transaction.manager:
 | 
			
		||||
                    f.save(Session)
 | 
			
		||||
                    Session.flush()
 | 
			
		||||
                    self.request.session.flash('The book "%s" has been loaned.' % f.book.value)
 | 
			
		||||
 | 
			
		||||
                if self.request.params.get('keep-going') == '1':
 | 
			
		||||
                    return HTTPFound(location=self.request.current_route_url())
 | 
			
		||||
 | 
			
		||||
                return HTTPFound(location=f.home_url)
 | 
			
		||||
 | 
			
		||||
        return {'form': f}
 | 
			
		||||
 | 
			
		||||
    def make_form(self, request, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Returns a :class:`edbob.pyramid.forms.Form` instance.
 | 
			
		||||
        """
 | 
			
		||||
        template = kwargs.pop('template', self.template or '%s.mako' % self.url)
 | 
			
		||||
        return SimpleForm(request, template=template, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def form(self, request):
 | 
			
		||||
        """
 | 
			
		||||
        Should create and return a :class:`edbob.pyramid.forms.Form` instance
 | 
			
		||||
        for the view.
 | 
			
		||||
        """
 | 
			
		||||
        return self.make_form(request)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def add_route(cls, config, **kwargs):
 | 
			
		||||
        route = kwargs.get('route', cls.route)
 | 
			
		||||
        url = kwargs.get('url', cls.url)
 | 
			
		||||
        permission = kwargs.get('permission', cls.permission or route)
 | 
			
		||||
        template = kwargs.get('template', cls.template or '%s.mako' % url)
 | 
			
		||||
        config.add_route(route, url)
 | 
			
		||||
        config.add_view(cls, route_name=route, renderer=template,
 | 
			
		||||
                        permission=permission, http_cache=0)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue