[Checkins] SVN: grok/trunk/src/grok/ * first stab at grok.EditForm
Wolfgang Schnerring
wosc at wosc.de
Thu Oct 19 08:09:14 EDT 2006
Log message for revision 70805:
* first stab at grok.EditForm
* refactored View to have module_info directly, not get it from the PageTemplate
Changed:
U grok/trunk/src/grok/__init__.py
U grok/trunk/src/grok/_grok.py
U grok/trunk/src/grok/components.py
A grok/trunk/src/grok/ftests/form/
A grok/trunk/src/grok/ftests/form/__init__.py
A grok/trunk/src/grok/ftests/form/form.py
U grok/trunk/src/grok/ftests/test_grok_functional.py
U grok/trunk/src/grok/interfaces.py
A grok/trunk/src/grok/tests/form/
A grok/trunk/src/grok/tests/form/__init__.py
A grok/trunk/src/grok/tests/form/form.py
U grok/trunk/src/grok/tests/test_grok.py
-=-
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/__init__.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -30,6 +30,7 @@
from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC
from grok.components import PageTemplate, Utility, Container, Traverser
+from grok.components import EditForm
from grok.directive import context, name, template, templatedir
from grok._grok import do_grok as grok # Avoid name clash within _grok
from grok._grok import SubscribeDecorator as subscribe
Modified: grok/trunk/src/grok/_grok.py
===================================================================
--- grok/trunk/src/grok/_grok.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/_grok.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -106,7 +106,7 @@
register_views(context, views, templates)
register_xmlrpc(context, xmlrpc_views)
register_traversers(context, traversers)
- register_unassociated_templates(context, templates)
+ register_unassociated_templates(context, templates, module_info)
register_subscribers(subscribers)
@@ -132,8 +132,13 @@
if isinstance(obj, grok.PageTemplate):
templates.register(name, obj)
- obj._annotateGrokInfo(module_info, name, module_info.dotted_name)
+ obj._annotateGrokInfo(name, module_info.dotted_name)
continue
+ # XXX refactor
+ elif util.check_subclass(obj, grok.View):
+ obj.module_info = module_info
+ components[grok.View].append(obj)
+ continue
for candidate_class, found_list in components.items():
if util.check_subclass(obj, candidate_class):
@@ -168,10 +173,7 @@
f.close()
template = grok.PageTemplate(contents)
- template._annotateGrokInfo(module_info, template_name,
- template_path)
- #template.__grok_name__ = template_name
- #template.__grok_location__ = template_path
+ template._annotateGrokInfo(template_name, template_path)
inline_template = templates.get(template_name)
if inline_template:
@@ -282,12 +284,14 @@
adapts=(factory_context, IBrowserRequest),
provides=IBrowserPublisher)
-def register_unassociated_templates(context, templates):
+def register_unassociated_templates(context, templates, module_info):
for name, unassociated in templates.listUnassociatedTemplates():
util.check_context(unassociated, context)
+ module_info_ = module_info
class TemplateView(grok.View):
template = unassociated
+ module_info = module_info_
templates.markAssociated(name)
Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/components.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -17,12 +17,16 @@
import persistent
from zope import component
from zope import interface
+from zope import schema
from zope.security.proxy import removeSecurityProxy
from zope.publisher.browser import BrowserPage
from zope.publisher.interfaces import NotFound
from zope.publisher.interfaces.browser import (IBrowserPublisher,
IBrowserRequest)
from zope.pagetemplate import pagetemplate
+from zope.formlib import form
+from zope.formlib.namedtemplate import INamedTemplate
+from zope.schema.interfaces import IField
from zope.app.pagetemplate.engine import TrustedAppPT
from zope.app.publisher.browser import getDefaultViewName
@@ -34,9 +38,14 @@
from grok import util, security
class Model(persistent.Persistent):
- pass
+ def __new__(class_, *args, **kw):
+ instance = super(Model, class_).__new__(class_, args, kw)
+ for field in schema_fields(instance):
+ setattr(instance, field.__name__, None)
+ return instance
+
class Container(BTreeContainer):
pass
@@ -61,6 +70,8 @@
# Jim would say: WAAAAAAAAAAAAH!
self.context = removeSecurityProxy(context)
self.request = removeSecurityProxy(request)
+ self.directory_resource = component.queryAdapter(self.request,
+ interface.Interface, name=self.module_info.package_dotted_name)
def __call__(self):
self.before()
@@ -73,12 +84,8 @@
namespace['request'] = self.request
namespace['view'] = self
namespace['context'] = self.context
-
- module_info = template.__grok_module_info__
- directory_resource = component.queryAdapter(self.request,
- interface.Interface, name=module_info.package_dotted_name)
- # XXX need to check whether we really want None here
- namespace['static'] = directory_resource
+ # XXX need to check whether we really want to put None here if missing
+ namespace['static'] = self.directory_resource
return template.pt_render(namespace)
def __getitem__(self, key):
@@ -113,8 +120,7 @@
return '<%s template in %s>' % (self.__grok_name__,
self.__grok_location__)
- def _annotateGrokInfo(self, module_info, name, location):
- self.__grok_module_info__ = module_info
+ def _annotateGrokInfo(self, name, location):
self.__grok_name__ = name
self.__grok_location__ = location
@@ -147,7 +153,6 @@
resource.__name__ = self.__name
return resource
-
class Traverser(object):
interface.implements(IBrowserPublisher)
@@ -184,3 +189,30 @@
traverser = util.class_annotation(self.context, 'grok.traverse', None)
if traverser:
return traverser(name)
+
+class EditForm(View, form.EditForm):
+ def __init__(self, context, request):
+ super(EditForm, self).__init__(context, request)
+
+ fields = schema_fields(self.context)
+ self.form_fields = form.Fields(*fields)
+
+ self.template = component.getAdapter(self, INamedTemplate,
+ name='default')
+
+ def __call__(self):
+ self.before()
+ self.update()
+ return self.render()
+
+def schema_fields(obj):
+ fields = []
+ fields_class = getattr(obj, 'fields', None)
+ if fields_class is not None:
+ for name in dir(fields_class):
+ field = getattr(fields_class, name)
+ if IField.providedBy(field):
+ if not getattr(field, '__name__', None):
+ field.__name__ = name
+ fields.append(field)
+ return fields
Added: grok/trunk/src/grok/ftests/form/__init__.py
===================================================================
--- grok/trunk/src/grok/ftests/form/__init__.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/ftests/form/__init__.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -0,0 +1 @@
+# this is a package
Added: grok/trunk/src/grok/ftests/form/form.py
===================================================================
--- grok/trunk/src/grok/ftests/form/form.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/ftests/form/form.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -0,0 +1,32 @@
+"""
+A grok.EditForm is a special grok.View that renders an edit form.
+
+ >>> import grok
+ >>> from grok.ftests.form.form import Mammoth
+ >>> grok.grok('grok.ftests.form.form')
+ >>> getRootFolder()["manfred"] = Mammoth()
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+ >>> browser.open("http://localhost/manfred/@@edit")
+ >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+ >>> browser.getControl(name="form.size").value = "Really big"
+ >>> browser.getControl("Apply").click()
+ >>> print browser.contents
+ <!DOCTYPE ...
+ ...Manfred the Mammoth...
+ ...Really big...
+ ...
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+ class fields:
+ name = schema.TextLine(title=u"Name")
+ size = schema.TextLine(title=u"Size")
+
+class Edit(grok.EditForm):
+ pass
Modified: grok/trunk/src/grok/ftests/test_grok_functional.py
===================================================================
--- grok/trunk/src/grok/ftests/test_grok_functional.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/ftests/test_grok_functional.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -56,7 +56,7 @@
def test_suite():
suite = unittest.TestSuite()
- for name in ['view', 'static', 'xmlrpc', 'traversal']:
+ for name in ['view', 'static', 'xmlrpc', 'traversal', 'form']:
suite.addTest(suiteFromPackage(name))
return suite
Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/interfaces.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -26,6 +26,7 @@
View = interface.Attribute("Base class for browser views.")
XMLRPC = interface.Attribute("Base class for XML-RPC methods.")
Traverser = interface.Attribute("Base class for custom traversers.")
+ EditForm = interface.Attribute("Base class for edit forms.")
class IGrokErrors(interface.Interface):
Added: grok/trunk/src/grok/tests/form/__init__.py
===================================================================
--- grok/trunk/src/grok/tests/form/__init__.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/tests/form/__init__.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -0,0 +1 @@
+# this is a package
Added: grok/trunk/src/grok/tests/form/form.py
===================================================================
--- grok/trunk/src/grok/tests/form/form.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/tests/form/form.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -0,0 +1,45 @@
+"""
+A grok.Model may contain a nested class named 'fields'. All attributes of
+'fields' that provide IField will cause attributes of the same name to appear on
+the grok.Model:
+
+ >>> grok.grok(__name__)
+ >>> manfred = Mammoth()
+ >>> print manfred.name
+ None
+ >>> print manfred.size
+ None
+ >>> manfred.somethingelse
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'Mammoth' object has no attribute 'somethingelse'
+
+A grok.EditForm is a special grok.View that renders an edit form.
+
+We need to set up the default formlib template first, because even though we
+don't use the formlib NamedTemplates directly they need to be present to create
+a formlib form.
+
+ >>> from zope import component
+ >>> from zope.formlib import form
+ >>> component.provideAdapter(form.default_page_template, name='default')
+
+ >>> from zope.publisher.browser import TestRequest
+ >>> request = TestRequest()
+ >>> view = component.getMultiAdapter((manfred, request), name='edit')
+ >>> len(view.form_fields)
+ 2
+ >>> [w.__name__ for w in view.form_fields]
+ ['name', 'size']
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+ class fields:
+ name = schema.TextLine(title=u"Name")
+ size = schema.TextLine(title=u"Size")
+ somethingelse = None
+
+class Edit(grok.EditForm):
+ pass
Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py 2006-10-19 11:57:45 UTC (rev 70804)
+++ grok/trunk/src/grok/tests/test_grok.py 2006-10-19 12:09:13 UTC (rev 70805)
@@ -34,7 +34,7 @@
suite = unittest.TestSuite()
for name in ['adapter', 'error', 'view', 'security', 'scan', 'event',
'zcml', 'static', 'utility', 'xmlrpc', 'container',
- 'traversal']:
+ 'traversal', 'form']:
suite.addTest(suiteFromPackage(name))
return suite
More information about the Checkins
mailing list