Add master4, refactor customers view to use it
This commit is contained in:
		
							parent
							
								
									ab16ffc823
								
							
						
					
					
						commit
						63290154eb
					
				
					 6 changed files with 348 additions and 18 deletions
				
			
		|  | @ -1,4 +1,6 @@ | |||
| ## -*- coding: utf-8; -*- | ||||
| <%inherit file="/mobile/master/create.mako" /> | ||||
| 
 | ||||
| <%def name="title()">New ${model_title} Row</%def> | ||||
| 
 | ||||
| ${parent.body()} | ||||
|  |  | |||
|  | @ -8,5 +8,5 @@ | |||
| ${parent.body()} | ||||
| 
 | ||||
| % if master.mobile_rows_editable and instance_editable and request.has_perm('{}.edit_row'.format(permission_prefix)): | ||||
|   ${h.link_to("Edit", url('mobile.{}.edit_row'.format(route_prefix), uuid=instance.uuid), class_='ui-btn')} | ||||
|   ${h.link_to("Edit", url('mobile.{}.edit_row'.format(route_prefix), uuid=instance.batch_uuid, row_uuid=instance.uuid), class_='ui-btn')} | ||||
| % endif | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # -*- coding: utf-8; -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2017 Lance Edgar | ||||
| #  Copyright © 2010-2018 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
|  | @ -30,6 +30,7 @@ from .core import View | |||
| from .master import MasterView | ||||
| from .master2 import MasterView2 | ||||
| from .master3 import MasterView3 | ||||
| from .master4 import MasterView4 | ||||
| 
 | ||||
| # TODO: deprecate / remove some of this | ||||
| from .autocomplete import AutocompleteView | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2017 Lance Edgar | ||||
| #  Copyright © 2010-2018 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
|  | @ -39,7 +39,7 @@ from webhelpers2.html import HTML, tags | |||
| 
 | ||||
| from tailbone import grids | ||||
| from tailbone.db import Session | ||||
| from tailbone.views import MasterView3 as MasterView, AutocompleteView | ||||
| from tailbone.views import MasterView4 as MasterView, AutocompleteView | ||||
| 
 | ||||
| from rattail.db import model | ||||
| 
 | ||||
|  | @ -83,6 +83,19 @@ class CustomersView(MasterView): | |||
|         'groups', | ||||
|     ] | ||||
| 
 | ||||
|     mobile_form_fields = [ | ||||
|         'id', | ||||
|         'name', | ||||
|         'default_phone', | ||||
|         'default_email', | ||||
|         'default_address', | ||||
|         'email_preference', | ||||
|         'active_in_pos', | ||||
|         'active_in_pos_sticky', | ||||
|         'people', | ||||
|         'groups', | ||||
|     ] | ||||
| 
 | ||||
|     def configure_grid(self, g): | ||||
|         super(CustomersView, self).configure_grid(g) | ||||
| 
 | ||||
|  | @ -286,13 +299,6 @@ class CustomersView(MasterView): | |||
|             items.append(HTML.tag('li', tags.link_to(text, url))) | ||||
|         return HTML.tag('ul', HTML.literal('').join(items)) | ||||
| 
 | ||||
|     # def configure_mobile_fieldset(self, fs): | ||||
|     #     fs.configure( | ||||
|     #         include=[ | ||||
|     #             fs.email, | ||||
|     #             fs.phone, | ||||
|     #         ]) | ||||
| 
 | ||||
|     def get_version_child_classes(self): | ||||
|         return [ | ||||
|             (model.CustomerPhoneNumber, 'parent_uuid'), | ||||
|  |  | |||
|  | @ -824,6 +824,9 @@ class MasterView(View): | |||
|     def validate_mobile_form(self, form): | ||||
|         return form.validate() | ||||
| 
 | ||||
|     def validate_row_form(self, form): | ||||
|         return form.validate() | ||||
| 
 | ||||
|     def save_edit_form(self, form): | ||||
|         self.save_form(form) | ||||
|         self.after_edit(form.fieldset.model) | ||||
|  | @ -1741,10 +1744,9 @@ class MasterView(View): | |||
|         index_url = self.get_action_url('view', parent) | ||||
|         form = self.make_row_form(self.model_row_class, cancel_url=index_url) | ||||
|         if self.request.method == 'POST': | ||||
|             if form.validate(): | ||||
|             if self.validate_row_form(form): | ||||
|                 self.before_create_row(form) | ||||
|                 self.save_create_row_form(form) | ||||
|                 obj = form.fieldset.model | ||||
|                 obj = self.save_create_row_form(form) or form.fieldset.model | ||||
|                 self.after_create_row(obj) | ||||
|                 return self.redirect_after_create_row(obj) | ||||
|         return self.render_to_response('create_row', { | ||||
|  | @ -1775,7 +1777,7 @@ class MasterView(View): | |||
|         instance_url = self.get_action_url('view', parent, mobile=True) | ||||
|         form = self.make_mobile_row_form(self.model_row_class, cancel_url=instance_url) | ||||
|         if self.request.method == 'POST': | ||||
|             if form.validate(): | ||||
|             if self.validate_mobile_row_form(form): | ||||
|                 self.before_create_row(form) | ||||
|                 # let save() return alternate object if necessary | ||||
|                 obj = self.save_create_row_form(form) or form.fieldset.model | ||||
|  | @ -1835,7 +1837,7 @@ class MasterView(View): | |||
|         form = self.make_row_form(row) | ||||
| 
 | ||||
|         if self.request.method == 'POST': | ||||
|             if form.validate(): | ||||
|             if self.validate_row_form(form): | ||||
|                 self.save_edit_row_form(form) | ||||
|                 return self.redirect_after_edit_row(row) | ||||
| 
 | ||||
|  | @ -1860,7 +1862,7 @@ class MasterView(View): | |||
|         form = self.make_mobile_row_form(row) | ||||
| 
 | ||||
|         if self.request.method == 'POST': | ||||
|             if form.validate(): | ||||
|             if self.validate_mobile_row_form(form): | ||||
|                 self.save_edit_row_form(form) | ||||
|                 return self.redirect_after_edit_row(row, mobile=True) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										319
									
								
								tailbone/views/master4.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								tailbone/views/master4.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,319 @@ | |||
| # -*- coding: utf-8; -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2018 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
| #  Rattail is free software: you can redistribute it and/or modify it under the | ||||
| #  terms of the GNU General Public License as published by the Free Software | ||||
| #  Foundation, either version 3 of the License, or (at your option) any later | ||||
| #  version. | ||||
| # | ||||
| #  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| #  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||
| #  details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public License along with | ||||
| #  Rattail.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| ################################################################################ | ||||
| """ | ||||
| Master View (v4) | ||||
| """ | ||||
| 
 | ||||
| from __future__ import unicode_literals, absolute_import | ||||
| 
 | ||||
| import deform | ||||
| 
 | ||||
| from tailbone import forms2 as forms | ||||
| from tailbone.views import MasterView3 | ||||
| 
 | ||||
| 
 | ||||
| class MasterView4(MasterView3): | ||||
|     """ | ||||
|     Base "master" view class.  All model master views should derive from this. | ||||
|     """ | ||||
|     row_labels = {} | ||||
| 
 | ||||
|     def make_mobile_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs): | ||||
|         """ | ||||
|         Creates a new mobile form for the given model class/instance. | ||||
|         """ | ||||
|         if factory is None: | ||||
|             factory = self.get_mobile_form_factory() | ||||
|         if fields is None: | ||||
|             fields = self.get_mobile_form_fields() | ||||
|         if schema is None: | ||||
|             schema = self.make_mobile_form_schema() | ||||
| 
 | ||||
|         if not self.creating: | ||||
|             kwargs['model_instance'] = instance | ||||
|         kwargs = self.make_mobile_form_kwargs(**kwargs) | ||||
|         form = factory(fields, schema, **kwargs) | ||||
|         self.configure_mobile_form(form) | ||||
|         return form | ||||
| 
 | ||||
|     def make_row_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs): | ||||
|         """ | ||||
|         Creates a new row form for the given model class/instance. | ||||
|         """ | ||||
|         if factory is None: | ||||
|             factory = self.get_row_form_factory() | ||||
|         if fields is None: | ||||
|             fields = self.get_row_form_fields() | ||||
|         if schema is None: | ||||
|             schema = self.make_row_form_schema() | ||||
| 
 | ||||
|         if not self.creating: | ||||
|             kwargs['model_instance'] = instance | ||||
|         kwargs = self.make_row_form_kwargs(**kwargs) | ||||
|         form = factory(fields, schema, **kwargs) | ||||
|         self.configure_row_form(form) | ||||
|         return form | ||||
| 
 | ||||
|     def make_mobile_row_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs): | ||||
|         """ | ||||
|         Creates a new mobile form for the given model class/instance. | ||||
|         """ | ||||
|         if factory is None: | ||||
|             factory = self.get_mobile_row_form_factory() | ||||
|         if fields is None: | ||||
|             fields = self.get_mobile_row_form_fields() | ||||
|         if schema is None: | ||||
|             schema = self.make_mobile_row_form_schema() | ||||
| 
 | ||||
|         if not self.creating: | ||||
|             kwargs['model_instance'] = instance | ||||
|         kwargs = self.make_mobile_row_form_kwargs(**kwargs) | ||||
|         form = factory(fields, schema, **kwargs) | ||||
|         self.configure_mobile_row_form(form) | ||||
|         return form | ||||
| 
 | ||||
|     @classmethod | ||||
|     def get_mobile_form_factory(cls): | ||||
|         """ | ||||
|         Returns the factory or class which is to be used when creating new | ||||
|         mobile forms. | ||||
|         """ | ||||
|         return getattr(cls, 'mobile_form_factory', forms.Form) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def get_row_form_factory(cls): | ||||
|         """ | ||||
|         Returns the factory or class which is to be used when creating new row | ||||
|         forms. | ||||
|         """ | ||||
|         return getattr(cls, 'row_form_factory', forms.Form) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def get_mobile_row_form_factory(cls): | ||||
|         """ | ||||
|         Returns the factory or class which is to be used when creating new | ||||
|         mobile row forms. | ||||
|         """ | ||||
|         return getattr(cls, 'mobile_row_form_factory', forms.Form) | ||||
| 
 | ||||
|     def make_mobile_form_schema(self): | ||||
|         if not self.model_class: | ||||
|             # TODO | ||||
|             raise NotImplementedError | ||||
| 
 | ||||
|     def make_row_form_schema(self): | ||||
|         if not self.model_row_class: | ||||
|             # TODO | ||||
|             raise NotImplementedError | ||||
| 
 | ||||
|     def make_mobile_row_form_schema(self): | ||||
|         if not self.model_row_class: | ||||
|             # TODO | ||||
|             raise NotImplementedError | ||||
| 
 | ||||
|     def get_mobile_form_fields(self): | ||||
|         if hasattr(self, 'mobile_form_fields'): | ||||
|             return self.mobile_form_fields | ||||
|         # TODO | ||||
|         # raise NotImplementedError | ||||
| 
 | ||||
|     def get_row_form_fields(self): | ||||
|         if hasattr(self, 'row_form_fields'): | ||||
|             return self.row_form_fields | ||||
|         # TODO | ||||
|         # raise NotImplementedError | ||||
| 
 | ||||
|     def get_mobile_row_form_fields(self): | ||||
|         if hasattr(self, 'mobile_row_form_fields'): | ||||
|             return self.mobile_row_form_fields | ||||
|         # TODO | ||||
|         # raise NotImplementedError | ||||
| 
 | ||||
|     def make_mobile_form_kwargs(self, **kwargs): | ||||
|         """ | ||||
|         Return a dictionary of kwargs to be passed to the factory when creating | ||||
|         new mobile forms. | ||||
|         """ | ||||
|         defaults = { | ||||
|             'request': self.request, | ||||
|             'readonly': self.viewing, | ||||
|             'model_class': getattr(self, 'model_class', None), | ||||
|             'action_url': self.request.current_route_url(_query=None), | ||||
|         } | ||||
|         if self.creating: | ||||
|             defaults['cancel_url'] = self.get_index_url(mobile=True) | ||||
|         else: | ||||
|             instance = kwargs['model_instance'] | ||||
|             defaults['cancel_url'] = self.get_action_url('view', instance, mobile=True) | ||||
|         defaults.update(kwargs) | ||||
|         return defaults | ||||
| 
 | ||||
|     def make_row_form_kwargs(self, **kwargs): | ||||
|         """ | ||||
|         Return a dictionary of kwargs to be passed to the factory when creating | ||||
|         new row forms. | ||||
|         """ | ||||
|         defaults = { | ||||
|             'request': self.request, | ||||
|             'readonly': self.viewing, | ||||
|             'model_class': getattr(self, 'model_row_class', None), | ||||
|             'action_url': self.request.current_route_url(_query=None), | ||||
|         } | ||||
|         if self.creating: | ||||
|             kwargs.setdefault('cancel_url', self.request.get_referrer()) | ||||
|         else: | ||||
|             instance = kwargs['model_instance'] | ||||
|             kwargs.setdefault('cancel_url', self.get_row_action_url('view', instance)) | ||||
|         defaults.update(kwargs) | ||||
|         return defaults | ||||
| 
 | ||||
|     def make_mobile_row_form_kwargs(self, **kwargs): | ||||
|         """ | ||||
|         Return a dictionary of kwargs to be passed to the factory when creating | ||||
|         new mobile row forms. | ||||
|         """ | ||||
|         defaults = { | ||||
|             'request': self.request, | ||||
|             'readonly': self.viewing, | ||||
|             'model_class': getattr(self, 'model_row_class', None), | ||||
|             'action_url': self.request.current_route_url(_query=None), | ||||
|         } | ||||
|         if self.creating: | ||||
|             defaults['cancel_url'] = self.request.get_referrer() | ||||
|         else: | ||||
|             instance = kwargs['model_instance'] | ||||
|             defaults['cancel_url'] = self.get_row_action_url('view', instance, mobile=True) | ||||
|         defaults.update(kwargs) | ||||
|         return defaults | ||||
| 
 | ||||
|     def configure_mobile_form(self, form): | ||||
|         """ | ||||
|         Configure the primary mobile form. | ||||
|         """ | ||||
|         # TODO: is any of this stuff from configure_form() needed? | ||||
|         # if self.editing: | ||||
|         #     model_class = self.get_model_class(error=False) | ||||
|         #     if model_class: | ||||
|         #         mapper = orm.class_mapper(model_class) | ||||
|         #         for key in mapper.primary_key: | ||||
|         #             for field in form.fields: | ||||
|         #                 if field == key.name: | ||||
|         #                     form.set_readonly(field) | ||||
|         #                     break | ||||
|         # form.remove_field('uuid') | ||||
| 
 | ||||
|         self.set_labels(form) | ||||
| 
 | ||||
|     def configure_row_grid(self, grid): | ||||
|         super(MasterView4, self).configure_row_grid(grid) | ||||
|         self.set_row_labels(grid) | ||||
| 
 | ||||
|     def configure_row_form(self, form): | ||||
|         """ | ||||
|         Configure a row form. | ||||
|         """ | ||||
|         # TODO: is any of this stuff from configure_form() needed? | ||||
|         # if self.editing: | ||||
|         #     model_class = self.get_model_class(error=False) | ||||
|         #     if model_class: | ||||
|         #         mapper = orm.class_mapper(model_class) | ||||
|         #         for key in mapper.primary_key: | ||||
|         #             for field in form.fields: | ||||
|         #                 if field == key.name: | ||||
|         #                     form.set_readonly(field) | ||||
|         #                     break | ||||
|         # form.remove_field('uuid') | ||||
| 
 | ||||
|         self.set_row_labels(form) | ||||
| 
 | ||||
|     def configure_mobile_row_form(self, form): | ||||
|         """ | ||||
|         Configure the mobile row form. | ||||
|         """ | ||||
|         # TODO: is any of this stuff from configure_form() needed? | ||||
|         # if self.editing: | ||||
|         #     model_class = self.get_model_class(error=False) | ||||
|         #     if model_class: | ||||
|         #         mapper = orm.class_mapper(model_class) | ||||
|         #         for key in mapper.primary_key: | ||||
|         #             for field in form.fields: | ||||
|         #                 if field == key.name: | ||||
|         #                     form.set_readonly(field) | ||||
|         #                     break | ||||
|         # form.remove_field('uuid') | ||||
| 
 | ||||
|         self.set_row_labels(form) | ||||
| 
 | ||||
|     def set_row_labels(self, obj): | ||||
|         for key, label in self.row_labels.items(): | ||||
|             obj.set_label(key, label) | ||||
| 
 | ||||
|     def validate_mobile_form(self, form): | ||||
|         controls = self.request.POST.items() | ||||
|         try: | ||||
|             self.form_deserialized = form.validate(controls) | ||||
|         except deform.ValidationFailure: | ||||
|             return False | ||||
|         return True | ||||
| 
 | ||||
|     def validate_row_form(self, form): | ||||
|         controls = self.request.POST.items() | ||||
|         try: | ||||
|             self.form_deserialized = form.validate(controls) | ||||
|         except deform.ValidationFailure: | ||||
|             return False | ||||
|         return True | ||||
| 
 | ||||
|     def validate_mobile_row_form(self, form): | ||||
|         controls = self.request.POST.items() | ||||
|         try: | ||||
|             self.form_deserialized = form.validate(controls) | ||||
|         except deform.ValidationFailure: | ||||
|             return False | ||||
|         return True | ||||
| 
 | ||||
|     def save_mobile_create_form(self, form): | ||||
|         self.before_create(form) | ||||
|         with self.Session.no_autoflush: | ||||
|             obj = self.objectify(form, self.form_deserialized) | ||||
|             self.before_create_flush(obj, form) | ||||
|         self.Session.add(obj) | ||||
|         self.Session.flush() | ||||
|         return obj | ||||
| 
 | ||||
|     # TODO: still need to verify this logic | ||||
|     def save_create_row_form(self, form): | ||||
|         # self.before_create(form) | ||||
|         # with self.Session().no_autoflush: | ||||
|         #     obj = self.objectify(form, self.form_deserialized) | ||||
|         #     self.before_create_flush(obj, form) | ||||
|         obj = self.objectify(form, self.form_deserialized) | ||||
|         self.Session.add(obj) | ||||
|         self.Session.flush() | ||||
|         return obj | ||||
| 
 | ||||
|     def save_edit_row_form(self, form): | ||||
|         obj = self.objectify(form, self.form_deserialized) | ||||
|         self.after_edit_row(obj) | ||||
|         self.Session.flush() | ||||
|         return obj | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar