CRUD form overhaul..etc.
This commit is contained in:
		
							parent
							
								
									dbd99303c4
								
							
						
					
					
						commit
						5b5b0c8738
					
				
					 14 changed files with 207 additions and 218 deletions
				
			
		| 
						 | 
				
			
			@ -36,8 +36,11 @@ from webhelpers.html.tags import literal
 | 
			
		|||
import formalchemy
 | 
			
		||||
from formalchemy.validators import accepts_none
 | 
			
		||||
 | 
			
		||||
import edbob
 | 
			
		||||
from edbob.lib import pretty
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.time import localize
 | 
			
		||||
from edbob.util import requires_impl
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid.forms.formalchemy.fieldset import *
 | 
			
		||||
from edbob.pyramid.forms.formalchemy.fields import *
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +68,50 @@ engine = TemplateEngine()
 | 
			
		|||
formalchemy.config.engine = engine
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AlchemyForm(edbob.Object):
 | 
			
		||||
    """
 | 
			
		||||
    Form to contain a :class:`formalchemy.FieldSet` instance.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    create_label = "Create"
 | 
			
		||||
    update_label = "Update"
 | 
			
		||||
 | 
			
		||||
    allow_successive_creates = False
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request, fieldset, **kwargs):
 | 
			
		||||
        edbob.Object.__init__(self, **kwargs)
 | 
			
		||||
        self.request = request
 | 
			
		||||
        self.fieldset = fieldset
 | 
			
		||||
 | 
			
		||||
    def _get_readonly(self):
 | 
			
		||||
        return self.fieldset.readonly
 | 
			
		||||
 | 
			
		||||
    def _set_readonly(self, val):
 | 
			
		||||
        self.fieldset.readonly = val
 | 
			
		||||
 | 
			
		||||
    readonly = property(_get_readonly, _set_readonly)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def successive_create_label(self):
 | 
			
		||||
        return "%s and continue" % self.create_label
 | 
			
		||||
 | 
			
		||||
    def render(self, **kwargs):
 | 
			
		||||
        kwargs['form'] = self
 | 
			
		||||
        if self.readonly:
 | 
			
		||||
            template = '/forms/form_readonly.mako'
 | 
			
		||||
        else:
 | 
			
		||||
            template = '/forms/form.mako'
 | 
			
		||||
        return render(template, kwargs)
 | 
			
		||||
 | 
			
		||||
    def save(self):
 | 
			
		||||
        self.fieldset.sync()
 | 
			
		||||
        Session.flush()
 | 
			
		||||
 | 
			
		||||
    def validate(self):
 | 
			
		||||
        self.fieldset.rebind(data=self.request.params)
 | 
			
		||||
        return self.fieldset.validate()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ChildGridField(formalchemy.Field):
 | 
			
		||||
    """
 | 
			
		||||
    Convenience class for including a child grid within a fieldset as a
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ __all__ = ['AutocompleteFieldRenderer', 'EnumFieldRenderer',
 | 
			
		|||
           'YesNoFieldRenderer']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def AutocompleteFieldRenderer(service_url, width='300px'):
 | 
			
		||||
def AutocompleteFieldRenderer(service_url, field_value=None, field_display=None, width='300px'):
 | 
			
		||||
    """
 | 
			
		||||
    Autocomplete renderer.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -46,10 +46,14 @@ def AutocompleteFieldRenderer(service_url, width='300px'):
 | 
			
		|||
        def focus_name(self):
 | 
			
		||||
            return self.name + '-textbox'
 | 
			
		||||
 | 
			
		||||
        @property
 | 
			
		||||
        def needs_focus(self):
 | 
			
		||||
            return not bool(self.value or field_value)
 | 
			
		||||
 | 
			
		||||
        def render(self, **kwargs):
 | 
			
		||||
            kwargs.setdefault('field_name', self.name)
 | 
			
		||||
            kwargs.setdefault('field_value', self.value)
 | 
			
		||||
            kwargs.setdefault('field_display', self.raw_value)
 | 
			
		||||
            kwargs.setdefault('field_value', self.value or field_value)
 | 
			
		||||
            kwargs.setdefault('field_display', self.raw_value or field_display)
 | 
			
		||||
            kwargs.setdefault('service_url', service_url)
 | 
			
		||||
            kwargs.setdefault('width', width)
 | 
			
		||||
            return render('/forms/field_autocomplete.mako', kwargs)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,10 +52,17 @@ class AlchemyGrid(Grid):
 | 
			
		|||
        self._formalchemy_grid = formalchemy.Grid(
 | 
			
		||||
            cls, instances, session=Session(), request=request)
 | 
			
		||||
        self._formalchemy_grid.prettify = prettify
 | 
			
		||||
        self.noclick_fields = []
 | 
			
		||||
 | 
			
		||||
    def __getattr__(self, attr):
 | 
			
		||||
        return getattr(self._formalchemy_grid, attr)
 | 
			
		||||
 | 
			
		||||
    def cell_class(self, field):
 | 
			
		||||
        classes = [field.name]
 | 
			
		||||
        if field.name in self.noclick_fields:
 | 
			
		||||
            classes.append('noclick')
 | 
			
		||||
        return ' '.join(classes)
 | 
			
		||||
 | 
			
		||||
    def checkbox(self, row):
 | 
			
		||||
        return tags.checkbox('check-'+row.uuid)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,13 @@
 | 
			
		|||
 | 
			
		||||
/******************************
 | 
			
		||||
 * Form Wrapper
 | 
			
		||||
 ******************************/
 | 
			
		||||
 | 
			
		||||
div.form-wrapper {
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/******************************
 | 
			
		||||
 * Context Menu
 | 
			
		||||
 ******************************/
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +28,6 @@ div.form,
 | 
			
		|||
div.fieldset-form,
 | 
			
		||||
div.fieldset {
 | 
			
		||||
    float: left;
 | 
			
		||||
    margin-left: 50px;
 | 
			
		||||
    margin-top: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,6 +105,7 @@ div.grid table tbody td.delete {
 | 
			
		|||
    background-position: center;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    min-width: 18px;
 | 
			
		||||
    width: 18px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.grid table tbody tr.hovering {
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +122,10 @@ div.grid table.checkable tbody tr {
 | 
			
		|||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.grid.clickable table tbody tr td.noclick {
 | 
			
		||||
    cursor: default;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* div.grid table.selectable tbody tr.selected, */
 | 
			
		||||
/* div.grid table.checkable tbody tr.selected { */
 | 
			
		||||
/*     background-color: #666666; */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,5 @@
 | 
			
		|||
<%inherit file="/base.mako" />
 | 
			
		||||
<%inherit file="/form.mako" />
 | 
			
		||||
 | 
			
		||||
<%def name="title()">${(fieldset.crud_title+' : '+fieldset.get_display_text() if fieldset.edit else 'New '+fieldset.crud_title) if crud else ''|n}</%def>
 | 
			
		||||
<%def name="title()">${"New "+form.pretty_name if form.creating else form.pretty_name+' : '+str(form.fieldset.model)}</%def>
 | 
			
		||||
 | 
			
		||||
<%def name="context_menu_items()"></%def>
 | 
			
		||||
 | 
			
		||||
<div class="form-wrapper">
 | 
			
		||||
 | 
			
		||||
  <ul class="context-menu">
 | 
			
		||||
    ${self.context_menu_items()}
 | 
			
		||||
  </ul>
 | 
			
		||||
 | 
			
		||||
  ${fieldset.render()|n}
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
${parent.body()}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,13 @@
 | 
			
		|||
<%inherit file="/base.mako" />
 | 
			
		||||
 | 
			
		||||
<%def name="buttons()"></%def>
 | 
			
		||||
<%def name="context_menu_items()"></%def>
 | 
			
		||||
 | 
			
		||||
<div class="wrapper">
 | 
			
		||||
<div class="form-wrapper">
 | 
			
		||||
 | 
			
		||||
  <div class="right">
 | 
			
		||||
    ${self.menu()}
 | 
			
		||||
  </div>
 | 
			
		||||
  <ul class="context-menu">
 | 
			
		||||
    ${self.context_menu_items()}
 | 
			
		||||
  </ul>
 | 
			
		||||
 | 
			
		||||
  <div class="left">
 | 
			
		||||
    <% print 'type (2) is', type(form) %>
 | 
			
		||||
    ${form.render(buttons=self.buttons)|n}
 | 
			
		||||
  </div>
 | 
			
		||||
  ${form.render()|n}
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,3 @@
 | 
			
		|||
<%inherit file="/edbob/form.mako" />
 | 
			
		||||
 | 
			
		||||
${parent.body()}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,64 +1,39 @@
 | 
			
		|||
<% _focus_rendered = False %>
 | 
			
		||||
 | 
			
		||||
<div class="fieldset-form ${class_}">
 | 
			
		||||
  ${h.form(fieldset.action_url+('?uuid='+fieldset.model.uuid) if fieldset.edit else '', enctype='multipart/form-data')}
 | 
			
		||||
% for error in fieldset.errors.get(None, []):
 | 
			
		||||
    <div class="fieldset-error">${error}</div>
 | 
			
		||||
% endfor
 | 
			
		||||
 | 
			
		||||
  % for error in fieldset.errors.get(None, []):
 | 
			
		||||
      <div class="fieldset-error">${error}</div>
 | 
			
		||||
  % endfor
 | 
			
		||||
% for field in fieldset.render_fields.itervalues():
 | 
			
		||||
 | 
			
		||||
  % for field in fieldset.render_fields.itervalues():
 | 
			
		||||
 | 
			
		||||
      % if field.requires_label:
 | 
			
		||||
          <div class="field-wrapper ${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
 | 
			
		||||
    % if field.requires_label:
 | 
			
		||||
        <div class="field-wrapper ${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 not _focus_rendered and (fieldset.focus == field or fieldset.focus is True):
 | 
			
		||||
              % if not field.is_readonly():
 | 
			
		||||
                  <script language="javascript" type="text/javascript">
 | 
			
		||||
                    $(function() {
 | 
			
		||||
                        % if hasattr(field.renderer, 'focus_name'):
 | 
			
		||||
                            $('#${field.renderer.focus_name}').focus();
 | 
			
		||||
                        % else:
 | 
			
		||||
                            $('#${field.renderer.name}').focus();
 | 
			
		||||
                        % endif
 | 
			
		||||
                    });
 | 
			
		||||
                  </script>
 | 
			
		||||
                  <% _focus_rendered = True %>
 | 
			
		||||
              % endif
 | 
			
		||||
          % if 'instructions' in field.metadata:
 | 
			
		||||
              <span class="instructions">${field.metadata['instructions']}</span>
 | 
			
		||||
          % endif
 | 
			
		||||
      % endif
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
  % endfor
 | 
			
		||||
        % if not _focus_rendered and (fieldset.focus == field or fieldset.focus is True):
 | 
			
		||||
            % if not field.is_readonly() and getattr(field.renderer, 'needs_focus', True):
 | 
			
		||||
                <script language="javascript" type="text/javascript">
 | 
			
		||||
                  $(function() {
 | 
			
		||||
                      % if hasattr(field.renderer, 'focus_name'):
 | 
			
		||||
                          $('#${field.renderer.focus_name}').focus();
 | 
			
		||||
                      % else:
 | 
			
		||||
                          $('#${field.renderer.name}').focus();
 | 
			
		||||
                      % endif
 | 
			
		||||
                  });
 | 
			
		||||
                </script>
 | 
			
		||||
                <% _focus_rendered = True %>
 | 
			
		||||
            % endif
 | 
			
		||||
        % endif
 | 
			
		||||
    % endif
 | 
			
		||||
 | 
			
		||||
  % if fieldset.allow_continue:
 | 
			
		||||
      <div class="checkbox">
 | 
			
		||||
        ${h.checkbox('add-another', checked=True)}
 | 
			
		||||
        <label for="add-another">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 = '${fieldset.home_url}';
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
% endfor
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,62 +1,15 @@
 | 
			
		|||
<% _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
 | 
			
		||||
  ${form.fieldset.render()|n}
 | 
			
		||||
 | 
			
		||||
  <div class="buttons">
 | 
			
		||||
    % if buttons:
 | 
			
		||||
        ${capture(buttons)}
 | 
			
		||||
    % else:
 | 
			
		||||
        ${h.submit('submit', "Save")}
 | 
			
		||||
        <button type="button" class="cancel">Cancel</button>
 | 
			
		||||
    ${h.submit('create', form.create_label if form.creating else form.update_label)}
 | 
			
		||||
    % if form.creating and form.allow_successive_creates:
 | 
			
		||||
        ${h.submit('create_and_continue', form.successive_create_label)}
 | 
			
		||||
    % endif
 | 
			
		||||
    <button type="button" onclick="location.href = '${form.cancel_url}';">Cancel</button>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  ${h.end_form()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script language="javascript" type="text/javascript">
 | 
			
		||||
  $(function() {
 | 
			
		||||
      $('button.cancel').click(function() {
 | 
			
		||||
          location.href = '${form.home_url}';
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								edbob/pyramid/templates/forms/form_readonly.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								edbob/pyramid/templates/forms/form_readonly.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
<div class="form">
 | 
			
		||||
  ${form.fieldset.render()|n}
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +23,7 @@
 | 
			
		|||
                <td class="checkbox">${grid.checkbox(row)}</td>
 | 
			
		||||
            % endif
 | 
			
		||||
            % for field in grid.iter_fields():
 | 
			
		||||
                <td class="${field.name}">${grid.render_field(field)}</td>
 | 
			
		||||
                <td class="${grid.cell_class(field)}">${grid.render_field(field)}</td>
 | 
			
		||||
            % endfor
 | 
			
		||||
            % for col in grid.extra_columns:
 | 
			
		||||
                <td class="noclick ${col.name}">${col.callback(row)}</td>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,9 +33,10 @@ from webhelpers.html import literal
 | 
			
		|||
from webhelpers.html.tags import link_to
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid.views.core import *
 | 
			
		||||
from edbob.pyramid.views.autocomplete import *
 | 
			
		||||
from edbob.pyramid.views.form import *
 | 
			
		||||
from edbob.pyramid.views.grids import *
 | 
			
		||||
from edbob.pyramid.views.crud import *
 | 
			
		||||
from edbob.pyramid.views.autocomplete import *
 | 
			
		||||
# from edbob.pyramid.views.form import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def forbidden(request):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,22 +28,20 @@
 | 
			
		|||
 | 
			
		||||
from pyramid.httpexceptions import HTTPFound
 | 
			
		||||
 | 
			
		||||
import formalchemy
 | 
			
		||||
 | 
			
		||||
from edbob.pyramid import Session
 | 
			
		||||
from edbob.pyramid.forms.formalchemy.fieldset import FieldSet
 | 
			
		||||
from edbob.pyramid.forms.formalchemy import AlchemyForm
 | 
			
		||||
from edbob.pyramid.views.core import View
 | 
			
		||||
from edbob.util import requires_impl
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Crud(object):
 | 
			
		||||
__all__ = ['CrudView']
 | 
			
		||||
 | 
			
		||||
    routes = ['create', 'read', 'update', 'delete']
 | 
			
		||||
 | 
			
		||||
    route_prefix = None
 | 
			
		||||
    url_prefix = None
 | 
			
		||||
    template_prefix = None
 | 
			
		||||
    permission_prefix = None
 | 
			
		||||
class CrudView(View):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, request):
 | 
			
		||||
        self.request = request
 | 
			
		||||
    allow_successive_creates = False
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    @requires_impl(is_property=True)
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +49,7 @@ class Crud(object):
 | 
			
		|||
        pass
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def crud_title(self):
 | 
			
		||||
    def pretty_name(self):
 | 
			
		||||
        return self.mapped_class.__name__
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
| 
						 | 
				
			
			@ -65,64 +63,96 @@ class Crud(object):
 | 
			
		|||
 | 
			
		||||
    @property
 | 
			
		||||
    def cancel_route(self):
 | 
			
		||||
        return None
 | 
			
		||||
        return self.home_route
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def cancel_url(self):
 | 
			
		||||
        return self.request.route_url(self.cancel_route)
 | 
			
		||||
 | 
			
		||||
    def make_fieldset(self, model, **kwargs):
 | 
			
		||||
        if 'action_url' not in kwargs:
 | 
			
		||||
            kwargs['action_url'] = self.request.current_route_url()
 | 
			
		||||
        if 'home_url' not in kwargs:
 | 
			
		||||
            kwargs['home_url'] = self.home_url
 | 
			
		||||
 | 
			
		||||
        kwargs.setdefault('session', Session())
 | 
			
		||||
        fs = FieldSet(model, **kwargs)
 | 
			
		||||
        fs.create = model is self.mapped_class
 | 
			
		||||
        fs.update = not fs.create
 | 
			
		||||
        return fs
 | 
			
		||||
        fieldset = formalchemy.FieldSet(model, **kwargs)
 | 
			
		||||
        return fieldset
 | 
			
		||||
 | 
			
		||||
    def fieldset(self, obj):
 | 
			
		||||
        return self.make_fieldset(obj)
 | 
			
		||||
    def fieldset(self, model):
 | 
			
		||||
        return self.make_fieldset(model)
 | 
			
		||||
 | 
			
		||||
    def post_sync(self, fs):
 | 
			
		||||
        pass
 | 
			
		||||
    def make_form(self, model, **kwargs):
 | 
			
		||||
        self.creating = model is self.mapped_class
 | 
			
		||||
        self.updating = not self.creating
 | 
			
		||||
 | 
			
		||||
    def validation_failed(self, fs):
 | 
			
		||||
        pass
 | 
			
		||||
        fieldset = self.fieldset(model)
 | 
			
		||||
        kwargs.setdefault('pretty_name', self.pretty_name)
 | 
			
		||||
        kwargs.setdefault('action_url', self.request.current_route_url())
 | 
			
		||||
        kwargs.setdefault('cancel_url', self.cancel_url)
 | 
			
		||||
        kwargs.setdefault('creating', self.creating)
 | 
			
		||||
        kwargs.setdefault('updating', self.updating)
 | 
			
		||||
        form = AlchemyForm(self.request, fieldset, **kwargs)
 | 
			
		||||
 | 
			
		||||
        if form.creating:
 | 
			
		||||
            if hasattr(self, 'create_label'):
 | 
			
		||||
                form.create_label = self.create_label
 | 
			
		||||
            if self.allow_successive_creates:
 | 
			
		||||
                form.allow_successive_creates = True
 | 
			
		||||
                if hasattr(self, 'successive_create_label'):
 | 
			
		||||
                    form.successive_create_label = self.successive_create_label
 | 
			
		||||
 | 
			
		||||
        return form
 | 
			
		||||
 | 
			
		||||
    def form(self, model):
 | 
			
		||||
        return self.make_form(model)
 | 
			
		||||
 | 
			
		||||
    def crud(self, model, readonly=False):
 | 
			
		||||
 | 
			
		||||
        fs = self.fieldset(model)
 | 
			
		||||
        form = self.form(model)
 | 
			
		||||
        if readonly:
 | 
			
		||||
            fs.readonly = True
 | 
			
		||||
        if not fs.readonly and self.request.POST:
 | 
			
		||||
            fs.rebind(data=self.request.params)
 | 
			
		||||
            if fs.validate():
 | 
			
		||||
            form.readonly = True
 | 
			
		||||
 | 
			
		||||
                fs.sync()
 | 
			
		||||
                Session.add(fs.model)
 | 
			
		||||
                Session.flush()
 | 
			
		||||
        if not form.readonly and self.request.POST:
 | 
			
		||||
            if form.validate():
 | 
			
		||||
                form.save()
 | 
			
		||||
 | 
			
		||||
                result = self.post_sync(fs)
 | 
			
		||||
                result = self.post_save(form)
 | 
			
		||||
                if result:
 | 
			
		||||
                    return result
 | 
			
		||||
 | 
			
		||||
                # Session.add(fs.model)
 | 
			
		||||
                # Session.flush()
 | 
			
		||||
                if fs.create:
 | 
			
		||||
                    self.flash_create(fs.model)
 | 
			
		||||
                if form.creating:
 | 
			
		||||
                    self.flash_create(form.fieldset.model)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.flash_update(fs.model)
 | 
			
		||||
                    self.flash_update(form.fieldset.model)
 | 
			
		||||
 | 
			
		||||
                if self.request.params.get('add-another') == '1':
 | 
			
		||||
                if (form.creating and form.allow_successive_creates
 | 
			
		||||
                    and self.request.params.get('create_and_continue')):
 | 
			
		||||
                    return HTTPFound(location=self.request.current_route_url())
 | 
			
		||||
 | 
			
		||||
                return HTTPFound(location=self.home_url)
 | 
			
		||||
 | 
			
		||||
            self.validation_failed(fs)
 | 
			
		||||
            self.validation_failed(form)
 | 
			
		||||
 | 
			
		||||
        if not fs.edit:
 | 
			
		||||
            fs.allow_continue = True
 | 
			
		||||
        kwargs = self.template_kwargs(form)
 | 
			
		||||
        kwargs['form'] = form
 | 
			
		||||
        return kwargs
 | 
			
		||||
 | 
			
		||||
        return {'fieldset': fs, 'crud': True}
 | 
			
		||||
    def template_kwargs(self, form):
 | 
			
		||||
        return {}
 | 
			
		||||
 | 
			
		||||
    def post_save(self, form):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def validation_failed(self, form):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def flash_create(self, model):
 | 
			
		||||
        self.request.session.flash("%s \"%s\" has been created." %
 | 
			
		||||
                                   (self.pretty_name, model))
 | 
			
		||||
 | 
			
		||||
    def flash_delete(self, model):
 | 
			
		||||
        self.request.session.flash("%s \"%s\" has been deleted." %
 | 
			
		||||
                                   (self.pretty_name, model))
 | 
			
		||||
        
 | 
			
		||||
    def flash_update(self, model):
 | 
			
		||||
        self.request.session.flash("%s \"%s\" has been updated." %
 | 
			
		||||
                                   (self.pretty_name, model))
 | 
			
		||||
 | 
			
		||||
    def create(self):
 | 
			
		||||
        return self.crud(self.mapped_class)
 | 
			
		||||
| 
						 | 
				
			
			@ -139,6 +169,9 @@ class Crud(object):
 | 
			
		|||
        assert model
 | 
			
		||||
        return self.crud(model)
 | 
			
		||||
 | 
			
		||||
    def pre_delete(self, model):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def delete(self):
 | 
			
		||||
        uuid = self.request.matchdict['uuid']
 | 
			
		||||
        model = Session.query(self.mapped_class).get(uuid) if uuid else None
 | 
			
		||||
| 
						 | 
				
			
			@ -150,38 +183,3 @@ class Crud(object):
 | 
			
		|||
        Session.flush() # Don't set flash message if delete fails.
 | 
			
		||||
        self.flash_delete(model)
 | 
			
		||||
        return HTTPFound(location=self.home_url)
 | 
			
		||||
 | 
			
		||||
    def flash_create(self, model):
 | 
			
		||||
        self.request.session.flash("%s \"%s\" has been created." %
 | 
			
		||||
                                   (self.crud_title, model))
 | 
			
		||||
 | 
			
		||||
    def flash_delete(self, model):
 | 
			
		||||
        self.request.session.flash("%s \"%s\" has been deleted." %
 | 
			
		||||
                                   (self.crud_title, model))
 | 
			
		||||
        
 | 
			
		||||
    def flash_update(self, model):
 | 
			
		||||
        self.request.session.flash("%s \"%s\" has been updated." %
 | 
			
		||||
                                   (self.crud_title, model))
 | 
			
		||||
 | 
			
		||||
    def pre_delete(self, model):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def add_routes(cls, config):
 | 
			
		||||
        route_name_prefix = cls.route_prefix or cls.mapped_class.__name__.lower()
 | 
			
		||||
        route_url_prefix = cls.url_prefix or '/%ss' % route_name_prefix
 | 
			
		||||
        renderer_prefix = cls.template_prefix or route_url_prefix
 | 
			
		||||
        permission_prefix = cls.permission_prefix or '%ss' % route_name_prefix
 | 
			
		||||
 | 
			
		||||
        for route in cls.routes:
 | 
			
		||||
            kw = dict(
 | 
			
		||||
                attr=route,
 | 
			
		||||
                route_name='%s.%s' % (route_name_prefix, route),
 | 
			
		||||
                renderer='%s/%s.mako' % (renderer_prefix, route),
 | 
			
		||||
                permission='%s.%s' % (permission_prefix, route),
 | 
			
		||||
                )
 | 
			
		||||
            if route == 'create':
 | 
			
		||||
                config.add_route(kw['route_name'], '%s/new' % route_url_prefix)
 | 
			
		||||
            else:
 | 
			
		||||
                config.add_route(kw['route_name'], '%s/{uuid}/%s' % (route_url_prefix, route))
 | 
			
		||||
            config.add_view(cls, http_cache=0, **kw)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue