Add new BatchMasterView for new-style batches.
				
					
				
			This commit is contained in:
		
							parent
							
								
									7338560fc3
								
							
						
					
					
						commit
						62221a1a25
					
				
					 14 changed files with 1112 additions and 93 deletions
				
			
		| 
						 | 
					@ -63,7 +63,8 @@ class FileFieldRenderer(fsblob.FileFieldRenderer):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_url(self, filename):
 | 
					    def get_url(self, filename):
 | 
				
			||||||
        batch = self.field.parent.model
 | 
					        batch = self.field.parent.model
 | 
				
			||||||
        return self.view.request.route_url('{0}.download'.format(self.view.route_prefix), uuid=batch.uuid)
 | 
					        return self.view.request.route_url('{}.download'.format(self.view.get_route_prefix()),
 | 
				
			||||||
 | 
					                                           uuid=batch.uuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def render(self, **kwargs):
 | 
					    def render(self, **kwargs):
 | 
				
			||||||
        return Base.render(self, **kwargs)
 | 
					        return Base.render(self, **kwargs)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ class Grid(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.width = width
 | 
					        self.width = width
 | 
				
			||||||
        self.checkboxes = checkboxes
 | 
					        self.checkboxes = checkboxes
 | 
				
			||||||
        self.row_attrs = row_attrs
 | 
					        self.row_attrs = row_attrs or {}
 | 
				
			||||||
        self.cell_attrs = cell_attrs
 | 
					        self.cell_attrs = cell_attrs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_default_filters(self):
 | 
					    def get_default_filters(self):
 | 
				
			||||||
| 
						 | 
					@ -160,10 +160,10 @@ class Grid(object):
 | 
				
			||||||
        instance attributes.
 | 
					        instance attributes.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        # Initial settings come from class defaults.
 | 
					        # Initial settings come from class defaults.
 | 
				
			||||||
        settings = {
 | 
					        settings = {}
 | 
				
			||||||
            'sortkey':  self.default_sortkey,
 | 
					        if self.sortable:
 | 
				
			||||||
            'sortdir':  self.default_sortdir,
 | 
					            settings['sortkey'] = self.default_sortkey
 | 
				
			||||||
        }
 | 
					            settings['sortdir'] = self.default_sortdir
 | 
				
			||||||
        if self.pageable:
 | 
					        if self.pageable:
 | 
				
			||||||
            settings['pagesize'] = self.default_pagesize
 | 
					            settings['pagesize'] = self.default_pagesize
 | 
				
			||||||
            settings['page'] = self.default_page
 | 
					            settings['page'] = self.default_page
 | 
				
			||||||
| 
						 | 
					@ -514,6 +514,7 @@ class Grid(object):
 | 
				
			||||||
        Render the complete grid, including filters.
 | 
					        Render the complete grid, including filters.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        kwargs['grid'] = self
 | 
					        kwargs['grid'] = self
 | 
				
			||||||
 | 
					        kwargs.setdefault('allow_save_defaults', True)
 | 
				
			||||||
        return render(template, kwargs)
 | 
					        return render(template, kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def render_grid(self, template='/newgrids/grid.mako', **kwargs):
 | 
					    def render_grid(self, template='/newgrids/grid.mako', **kwargs):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
  % if master.viewable and request.has_perm('{}.view'.format(permission_prefix)):
 | 
					  % if master.viewable and request.has_perm('{}.view'.format(permission_prefix)):
 | 
				
			||||||
      <li>${h.link_to("View this {}".format(model_title), action_url('view', instance))}</li>
 | 
					      <li>${h.link_to("View this {}".format(model_title), action_url('view', instance))}</li>
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
  % if master.deletable and master.deletable_instance(instance) and request.has_perm('{}.delete'.format(permission_prefix)):
 | 
					  % if master.deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)):
 | 
				
			||||||
      <li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
 | 
					      <li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
  % if master.creatable and request.has_perm('{}.create'.format(permission_prefix)):
 | 
					  % if master.creatable and request.has_perm('{}.create'.format(permission_prefix)):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,10 +5,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%def name="context_menu_items()">
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
  <li>${h.link_to("Back to {}".format(model_title_plural), index_url)}</li>
 | 
					  <li>${h.link_to("Back to {}".format(model_title_plural), index_url)}</li>
 | 
				
			||||||
  % if master.editable and request.has_perm('{}.edit'.format(permission_prefix)):
 | 
					  % if master.editable and instance_editable and request.has_perm('{}.edit'.format(permission_prefix)):
 | 
				
			||||||
      <li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
 | 
					      <li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
  % if master.deletable and master.deletable_instance(instance) and request.has_perm('{}.delete'.format(permission_prefix)):
 | 
					  % if master.deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)):
 | 
				
			||||||
      <li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
 | 
					      <li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
  % if master.creatable and request.has_perm('{}.create'.format(permission_prefix)):
 | 
					  % if master.creatable and request.has_perm('{}.create'.format(permission_prefix)):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								tailbone/templates/newbatch/create.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tailbone/templates/newbatch/create.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/create.mako" />
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
							
								
								
									
										59
									
								
								tailbone/templates/newbatch/edit.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								tailbone/templates/newbatch/edit.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,59 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/edit.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="head_tags()">
 | 
				
			||||||
 | 
					  ${parent.head_tags()}
 | 
				
			||||||
 | 
					  ${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
 | 
				
			||||||
 | 
					  <script type="text/javascript">
 | 
				
			||||||
 | 
					    $(function() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('.newgrid-wrapper').gridwrapper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('#save-refresh').click(function() {
 | 
				
			||||||
 | 
					            var form = $(this).parents('form');
 | 
				
			||||||
 | 
					            form.append($('<input type="hidden" name="refresh" value="true" />'));
 | 
				
			||||||
 | 
					            form.submit();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('#execute-batch').click(function() {
 | 
				
			||||||
 | 
					            $(this).button('option', 'label', "Executing, please wait...").button('disable');
 | 
				
			||||||
 | 
					            location.href = '${url('{}.execute'.format(route_prefix), uuid=batch.uuid)}';
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					  <style type="text/css">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .newgrid-wrapper {
 | 
				
			||||||
 | 
					        margin-top: 10px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="buttons()">
 | 
				
			||||||
 | 
					    <div class="buttons">
 | 
				
			||||||
 | 
					      % if master.refreshable:
 | 
				
			||||||
 | 
					          ${h.submit('save-refresh', "Save & Refresh Data")}
 | 
				
			||||||
 | 
					      % endif
 | 
				
			||||||
 | 
					      % if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)):
 | 
				
			||||||
 | 
					          <button type="button" id="execute-batch"${'' if execute_enabled else ' disabled="disabled"'}>${execute_title}</button>
 | 
				
			||||||
 | 
					      % endif
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="grid_tools()">
 | 
				
			||||||
 | 
					    % if not batch.executed:
 | 
				
			||||||
 | 
					        <p>${h.link_to("Delete all rows matching current search", url('{}.rows.bulk_delete'.format(route_prefix), uuid=batch.uuid))}</p>
 | 
				
			||||||
 | 
					    % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ul id="context-menu">
 | 
				
			||||||
 | 
					  ${self.context_menu_items()}
 | 
				
			||||||
 | 
					</ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="form-wrapper">
 | 
				
			||||||
 | 
					  ${form.render(buttons=capture(buttons))|n}
 | 
				
			||||||
 | 
					</div><!-- form-wrapper -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${rows_grid.render_complete(allow_save_defaults=False, tools=capture(self.grid_tools))|n}
 | 
				
			||||||
							
								
								
									
										3
									
								
								tailbone/templates/newbatch/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tailbone/templates/newbatch/index.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/index.mako" />
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
							
								
								
									
										54
									
								
								tailbone/templates/newbatch/view.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tailbone/templates/newbatch/view.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,54 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/view.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="head_tags()">
 | 
				
			||||||
 | 
					  ${parent.head_tags()}
 | 
				
			||||||
 | 
					  ${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
 | 
				
			||||||
 | 
					  <script type="text/javascript">
 | 
				
			||||||
 | 
					    $(function() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('.newgrid-wrapper').gridwrapper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $('#execute-batch').click(function() {
 | 
				
			||||||
 | 
					            $(this).button('option', 'label', "Executing, please wait...").button('disable');
 | 
				
			||||||
 | 
					            location.href = '${url('{}.execute'.format(route_prefix), uuid=batch.uuid)}';
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					  <style type="text/css">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .newgrid-wrapper {
 | 
				
			||||||
 | 
					        margin-top: 10px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  ${parent.context_menu_items()}
 | 
				
			||||||
 | 
					  % if request.has_perm('{}.csv'.format(permission_prefix)):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Download row data as CSV", url('{}.csv'.format(route_prefix), uuid=batch.uuid))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="buttons()">
 | 
				
			||||||
 | 
					    <div class="buttons">
 | 
				
			||||||
 | 
					      % if not form.readonly and batch.refreshable:
 | 
				
			||||||
 | 
					          ${h.submit('save-refresh', "Save & Refresh Data")}
 | 
				
			||||||
 | 
					      % endif
 | 
				
			||||||
 | 
					      % if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)):
 | 
				
			||||||
 | 
					          <button type="button" id="execute-batch"${'' if execute_enabled else ' disabled="disabled"'}>${execute_title}</button>
 | 
				
			||||||
 | 
					      % endif
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ul id="context-menu">
 | 
				
			||||||
 | 
					  ${self.context_menu_items()}
 | 
				
			||||||
 | 
					</ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="form-wrapper">
 | 
				
			||||||
 | 
					  ${form.render(form_id='batch-form', buttons=capture(buttons))|n}
 | 
				
			||||||
 | 
					</div><!-- form-wrapper -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${rows_grid|n}
 | 
				
			||||||
							
								
								
									
										19
									
								
								tailbone/templates/newbatch/view_row.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tailbone/templates/newbatch/view_row.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					## -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					<%inherit file="/master/view.mako" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="title()">${model_title}</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<%def name="context_menu_items()">
 | 
				
			||||||
 | 
					  <li>${h.link_to("Back to {}".format(batch_model_title), index_url)}</li>
 | 
				
			||||||
 | 
					  % if master.rows_editable and instance_editable and request.has_perm('{}.edit'.format(permission_prefix)):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					  % if master.rows_deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					  % if master.rows_creatable and request.has_perm('{}.create'.format(permission_prefix)):
 | 
				
			||||||
 | 
					      <li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
 | 
				
			||||||
 | 
					  % endif
 | 
				
			||||||
 | 
					</%def>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${parent.body()}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
## -*- coding: utf-8 -*-
 | 
					## -*- coding: utf-8 -*-
 | 
				
			||||||
<div class="newgrid-wrapper">
 | 
					<div class="newgrid-wrapper">
 | 
				
			||||||
  % if grid.filterable:
 | 
					  % if grid.filterable:
 | 
				
			||||||
      ${grid.render_filters()|n}
 | 
					      ${grid.render_filters(allow_save_defaults=allow_save_defaults)|n}
 | 
				
			||||||
  % endif
 | 
					  % endif
 | 
				
			||||||
  % if tools:
 | 
					  % if tools:
 | 
				
			||||||
      <div class="grid-tools">
 | 
					      <div class="grid-tools">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@
 | 
				
			||||||
      </select>
 | 
					      </select>
 | 
				
			||||||
      ${form.tag('button', type='button', id='default-filters', c="Default View")}
 | 
					      ${form.tag('button', type='button', id='default-filters', c="Default View")}
 | 
				
			||||||
      ${form.tag('button', type='button', id='clear-filters', c="No Filters")}
 | 
					      ${form.tag('button', type='button', id='clear-filters', c="No Filters")}
 | 
				
			||||||
      % if request.user:
 | 
					      % if allow_save_defaults and request.user:
 | 
				
			||||||
          ${form.tag('button', type='button', id='save-defaults', c="Save Defaults")}
 | 
					          ${form.tag('button', type='button', id='save-defaults', c="Save Defaults")}
 | 
				
			||||||
      % endif
 | 
					      % endif
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
################################################################################
 | 
					################################################################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  Rattail -- Retail Software Framework
 | 
					#  Rattail -- Retail Software Framework
 | 
				
			||||||
#  Copyright © 2010-2015 Lance Edgar
 | 
					#  Copyright © 2010-2016 Lance Edgar
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  This file is part of Rattail.
 | 
					#  This file is part of Rattail.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,9 @@
 | 
				
			||||||
Model Master View
 | 
					Model Master View
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals, absolute_import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sqlalchemy as sa
 | 
					import sqlalchemy as sa
 | 
				
			||||||
from sqlalchemy import orm
 | 
					from sqlalchemy import orm
 | 
				
			||||||
| 
						 | 
					@ -100,18 +102,24 @@ class MasterView(View):
 | 
				
			||||||
        View for creating a new model record.
 | 
					        View for creating a new model record.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.creating = True
 | 
					        self.creating = True
 | 
				
			||||||
        form = self.make_form(self.model_class)
 | 
					        form = self.make_form(self.get_model_class())
 | 
				
			||||||
        if self.request.method == 'POST':
 | 
					        if self.request.method == 'POST':
 | 
				
			||||||
            if form.validate():
 | 
					            if form.validate():
 | 
				
			||||||
                self.before_create(form)
 | 
					                self.save_create_form(form)
 | 
				
			||||||
                form.save()
 | 
					 | 
				
			||||||
                instance = form.fieldset.model
 | 
					                instance = form.fieldset.model
 | 
				
			||||||
                self.after_create(instance)
 | 
					                self.after_create(instance)
 | 
				
			||||||
                self.request.session.flash("{} {} has been created.".format(
 | 
					                self.request.session.flash("{} {} has been created.".format(
 | 
				
			||||||
                    self.get_model_title(), instance))
 | 
					                    self.get_model_title(), instance))
 | 
				
			||||||
                return self.redirect(self.get_action_url('view', instance))
 | 
					                return self.redirect_after_create(instance)
 | 
				
			||||||
        return self.render_to_response('create', {'form': form})
 | 
					        return self.render_to_response('create', {'form': form})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save_create_form(self, form):
 | 
				
			||||||
 | 
					        self.before_create(form)
 | 
				
			||||||
 | 
					        form.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def redirect_after_create(self, instance):
 | 
				
			||||||
 | 
					        return self.redirect(self.get_action_url('view', instance))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def view(self):
 | 
					    def view(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        View for viewing details of an existing model record.
 | 
					        View for viewing details of an existing model record.
 | 
				
			||||||
| 
						 | 
					@ -119,8 +127,11 @@ class MasterView(View):
 | 
				
			||||||
        self.viewing = True
 | 
					        self.viewing = True
 | 
				
			||||||
        instance = self.get_instance()
 | 
					        instance = self.get_instance()
 | 
				
			||||||
        form = self.make_form(instance)
 | 
					        form = self.make_form(instance)
 | 
				
			||||||
        return self.render_to_response('view', {'instance': instance,
 | 
					        return self.render_to_response('view', {
 | 
				
			||||||
 | 
					            'instance': instance,
 | 
				
			||||||
            'instance_title': self.get_instance_title(instance),
 | 
					            'instance_title': self.get_instance_title(instance),
 | 
				
			||||||
 | 
					            'instance_editable': self.editable_instance(instance),
 | 
				
			||||||
 | 
					            'instance_deletable': self.deletable_instance(instance),
 | 
				
			||||||
            'form': form})
 | 
					            'form': form})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def edit(self):
 | 
					    def edit(self):
 | 
				
			||||||
| 
						 | 
					@ -130,17 +141,27 @@ class MasterView(View):
 | 
				
			||||||
        self.editing = True
 | 
					        self.editing = True
 | 
				
			||||||
        instance = self.get_instance()
 | 
					        instance = self.get_instance()
 | 
				
			||||||
        form = self.make_form(instance)
 | 
					        form = self.make_form(instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.request.method == 'POST':
 | 
					        if self.request.method == 'POST':
 | 
				
			||||||
            if form.validate():
 | 
					            if form.validate():
 | 
				
			||||||
                self.save_form(form)
 | 
					                self.save_edit_form(form)
 | 
				
			||||||
                self.after_edit(instance)
 | 
					 | 
				
			||||||
                self.request.session.flash("{0} {1} has been updated.".format(
 | 
					                self.request.session.flash("{0} {1} has been updated.".format(
 | 
				
			||||||
                    self.get_model_title(), self.get_instance_title(instance)))
 | 
					                    self.get_model_title(), self.get_instance_title(instance)))
 | 
				
			||||||
                return self.redirect(self.get_action_url('view', instance))
 | 
					                return self.redirect_after_edit(instance)
 | 
				
			||||||
        return self.render_to_response('edit', {'instance': instance,
 | 
					
 | 
				
			||||||
 | 
					        return self.render_to_response('edit', {
 | 
				
			||||||
 | 
					            'instance': instance,
 | 
				
			||||||
            'instance_title': self.get_instance_title(instance),
 | 
					            'instance_title': self.get_instance_title(instance),
 | 
				
			||||||
 | 
					            'instance_deletable': self.deletable_instance(instance),
 | 
				
			||||||
            'form': form})
 | 
					            'form': form})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save_edit_form(self, form):
 | 
				
			||||||
 | 
					        self.save_form(form)
 | 
				
			||||||
 | 
					        self.after_edit(form.fieldset.model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def redirect_after_edit(self, instance):
 | 
				
			||||||
 | 
					        return self.redirect(self.get_action_url('view', instance))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def delete(self):
 | 
					    def delete(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        View for deleting an existing model record.
 | 
					        View for deleting an existing model record.
 | 
				
			||||||
| 
						 | 
					@ -181,7 +202,7 @@ class MasterView(View):
 | 
				
			||||||
        Returns the data model class for which the master view exists.
 | 
					        Returns the data model class for which the master view exists.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if not hasattr(cls, 'model_class') and error:
 | 
					        if not hasattr(cls, 'model_class') and error:
 | 
				
			||||||
            raise NotImplementedError("You must define the `model_class` for: {0}".format(cls))
 | 
					            raise NotImplementedError("You must define the `model_class` for: {}".format(cls))
 | 
				
			||||||
        return getattr(cls, 'model_class', None)
 | 
					        return getattr(cls, 'model_class', None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
| 
						 | 
					@ -213,7 +234,9 @@ class MasterView(View):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if hasattr(cls, 'model_title'):
 | 
					        if hasattr(cls, 'model_title'):
 | 
				
			||||||
            return cls.model_title
 | 
					            return cls.model_title
 | 
				
			||||||
        return cls.model_class.__name__
 | 
					        title = cls.get_model_class().__name__
 | 
				
			||||||
 | 
					        # convert "CamelCase" to "Camel Case"
 | 
				
			||||||
 | 
					        return re.sub(r'([a-z])([A-Z])', r'\g<1> \g<2>', title)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def get_model_title_plural(cls):
 | 
					    def get_model_title_plural(cls):
 | 
				
			||||||
| 
						 | 
					@ -279,7 +302,7 @@ class MasterView(View):
 | 
				
			||||||
        If that doesn't work, another attempt will be made using '/master' as
 | 
					        If that doesn't work, another attempt will be made using '/master' as
 | 
				
			||||||
        the template prefix.
 | 
					        the template prefix.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        data.update({
 | 
					        context = {
 | 
				
			||||||
            'master': self,
 | 
					            'master': self,
 | 
				
			||||||
            'model_title': self.get_model_title(),
 | 
					            'model_title': self.get_model_title(),
 | 
				
			||||||
            'model_title_plural': self.get_model_title_plural(),
 | 
					            'model_title_plural': self.get_model_title_plural(),
 | 
				
			||||||
| 
						 | 
					@ -287,16 +310,33 @@ class MasterView(View):
 | 
				
			||||||
            'permission_prefix': self.get_permission_prefix(),
 | 
					            'permission_prefix': self.get_permission_prefix(),
 | 
				
			||||||
            'index_url': self.get_index_url(),
 | 
					            'index_url': self.get_index_url(),
 | 
				
			||||||
            'action_url': self.get_action_url,
 | 
					            'action_url': self.get_action_url,
 | 
				
			||||||
        })
 | 
					        }
 | 
				
			||||||
        data.update(self.template_kwargs(**data))
 | 
					        context.update(data)
 | 
				
			||||||
        if hasattr(self, 'template_kwargs_{0}'.format(template)):
 | 
					        context.update(self.template_kwargs(**context))
 | 
				
			||||||
            data.update(getattr(self, 'template_kwargs_{0}'.format(template))(**data))
 | 
					        if hasattr(self, 'template_kwargs_{}'.format(template)):
 | 
				
			||||||
 | 
					            context.update(getattr(self, 'template_kwargs_{}'.format(template))(**context))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # First try the template path most specific to the view.
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            return render_to_response('{0}/{1}.mako'.format(self.get_template_prefix(), template),
 | 
					            return render_to_response('{}/{}.mako'.format(self.get_template_prefix(), template),
 | 
				
			||||||
                                      data, request=self.request)
 | 
					                                      context, request=self.request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        except IOError:
 | 
					        except IOError:
 | 
				
			||||||
            return render_to_response('/master/{0}.mako'.format(template),
 | 
					
 | 
				
			||||||
                                      data, request=self.request)
 | 
					            # Failing that, try one or more fallback templates.
 | 
				
			||||||
 | 
					            for fallback in self.get_fallback_templates(template):
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    return render_to_response(fallback, context, request=self.request)
 | 
				
			||||||
 | 
					                except IOError:
 | 
				
			||||||
 | 
					                    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # If we made it all the way here, we found no templates at all, in
 | 
				
			||||||
 | 
					            # which case re-attempt the first and let that error raise on up.
 | 
				
			||||||
 | 
					            return render_to_response('{}/{}.mako'.format(self.get_template_prefix(), template),
 | 
				
			||||||
 | 
					                                      context, request=self.request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_fallback_templates(self, template):
 | 
				
			||||||
 | 
					        return ['/master/{}.mako'.format(template)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def template_kwargs(self, **kwargs):
 | 
					    def template_kwargs(self, **kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -439,10 +479,14 @@ class MasterView(View):
 | 
				
			||||||
        data = self.get_data(session=kwargs.get('session'))
 | 
					        data = self.get_data(session=kwargs.get('session'))
 | 
				
			||||||
        kwargs = self.make_grid_kwargs(**kwargs)
 | 
					        kwargs = self.make_grid_kwargs(**kwargs)
 | 
				
			||||||
        grid = factory(key, self.request, data=data, model_class=self.get_model_class(error=False), **kwargs)
 | 
					        grid = factory(key, self.request, data=data, model_class=self.get_model_class(error=False), **kwargs)
 | 
				
			||||||
 | 
					        self._preconfigure_grid(grid)
 | 
				
			||||||
        self.configure_grid(grid)
 | 
					        self.configure_grid(grid)
 | 
				
			||||||
        grid.load_settings()
 | 
					        grid.load_settings()
 | 
				
			||||||
        return grid
 | 
					        return grid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _preconfigure_grid(self, grid):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def configure_grid(self, grid):
 | 
					    def configure_grid(self, grid):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Configure the grid, customizing as necessary.  Subclasses are
 | 
					        Configure the grid, customizing as necessary.  Subclasses are
 | 
				
			||||||
| 
						 | 
					@ -479,7 +523,17 @@ class MasterView(View):
 | 
				
			||||||
        users.  You would modify the base query to hide what you wanted,
 | 
					        users.  You would modify the base query to hide what you wanted,
 | 
				
			||||||
        regardless of the user's filter selections.
 | 
					        regardless of the user's filter selections.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return session.query(self.model_class)
 | 
					        return session.query(self.get_model_class())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_effective_query(self, session):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Convenience method which returns the "effective" query for the master
 | 
				
			||||||
 | 
					        grid, filtered and sorted to match what would show on the UI, but not
 | 
				
			||||||
 | 
					        paged etc.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        grid = self.make_grid(session=session, pageable=False,
 | 
				
			||||||
 | 
					                              main_actions=[], more_actions=[])
 | 
				
			||||||
 | 
					        return grid._fa_grid.rows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def checkbox(self, instance):
 | 
					    def checkbox(self, instance):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -507,7 +561,7 @@ class MasterView(View):
 | 
				
			||||||
        doing a database lookup.  If the instance cannot be found, raises 404.
 | 
					        doing a database lookup.  If the instance cannot be found, raises 404.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        key = self.request.matchdict[self.get_model_key()]
 | 
					        key = self.request.matchdict[self.get_model_key()]
 | 
				
			||||||
        instance = self.Session.query(self.model_class).get(key)
 | 
					        instance = self.Session.query(self.get_model_class()).get(key)
 | 
				
			||||||
        if not instance:
 | 
					        if not instance:
 | 
				
			||||||
            raise httpexceptions.HTTPNotFound()
 | 
					            raise httpexceptions.HTTPNotFound()
 | 
				
			||||||
        return instance
 | 
					        return instance
 | 
				
			||||||
| 
						 | 
					@ -529,7 +583,9 @@ class MasterView(View):
 | 
				
			||||||
        kwargs.setdefault('editing', self.editing)
 | 
					        kwargs.setdefault('editing', self.editing)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fieldset = self.make_fieldset(instance)
 | 
					        fieldset = self.make_fieldset(instance)
 | 
				
			||||||
 | 
					        self._preconfigure_fieldset(fieldset)
 | 
				
			||||||
        self.configure_fieldset(fieldset)
 | 
					        self.configure_fieldset(fieldset)
 | 
				
			||||||
 | 
					        self._postconfigure_fieldset(fieldset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kwargs.setdefault('action_url', self.request.current_route_url(_query=None))
 | 
					        kwargs.setdefault('action_url', self.request.current_route_url(_query=None))
 | 
				
			||||||
        if self.creating:
 | 
					        if self.creating:
 | 
				
			||||||
| 
						 | 
					@ -553,12 +609,18 @@ class MasterView(View):
 | 
				
			||||||
        fieldset.prettify = prettify
 | 
					        fieldset.prettify = prettify
 | 
				
			||||||
        return fieldset
 | 
					        return fieldset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _preconfigure_fieldset(self, fieldset):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def configure_fieldset(self, fieldset):
 | 
					    def configure_fieldset(self, fieldset):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Configure the given fieldset.
 | 
					        Configure the given fieldset.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        fieldset.configure()
 | 
					        fieldset.configure()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _postconfigure_fieldset(self, fieldset):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def before_create(self, form):
 | 
					    def before_create(self, form):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Event hook, called just after the form to create a new instance has
 | 
					        Event hook, called just after the form to create a new instance has
 | 
				
			||||||
| 
						 | 
					@ -570,6 +632,14 @@ class MasterView(View):
 | 
				
			||||||
        Event hook, called just after a new instance is saved.
 | 
					        Event hook, called just after a new instance is saved.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def editable_instance(self, instance):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns boolean indicating whether or not the given instance can be
 | 
				
			||||||
 | 
					        considered "editable".  Returns ``True`` by default; override as
 | 
				
			||||||
 | 
					        necessary.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def after_edit(self, instance):
 | 
					    def after_edit(self, instance):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Event hook, called just after an existing instance is saved.
 | 
					        Event hook, called just after an existing instance is saved.
 | 
				
			||||||
| 
						 | 
					@ -617,7 +687,7 @@ class MasterView(View):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Provide default configuration for a master view.
 | 
					        Provide default configuration for a master view.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return cls._defaults(config)
 | 
					        cls._defaults(config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def _defaults(cls, config):
 | 
					    def _defaults(cls, config):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -339,11 +339,7 @@ class ProductsView(MasterView):
 | 
				
			||||||
        Threat target for making a batch from current products query.
 | 
					        Threat target for making a batch from current products query.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        session = RattailSession()
 | 
					        session = RattailSession()
 | 
				
			||||||
 | 
					        products = self.get_effective_query(session)
 | 
				
			||||||
        grid = self.make_grid(session=session, pageable=False,
 | 
					 | 
				
			||||||
                              main_actions=[], more_actions=[])
 | 
					 | 
				
			||||||
        products = grid._fa_grid.rows
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        batch = provider.make_batch(session, products, progress)
 | 
					        batch = provider.make_batch(session, products, progress)
 | 
				
			||||||
        if not batch:
 | 
					        if not batch:
 | 
				
			||||||
            session.rollback()
 | 
					            session.rollback()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue