[Z3-sqlos] Re: [z3] sqlos: add view for SQLOS objects

Christian Lück christian.lueck at ruhr-uni-bochum.de
Sat Jan 21 01:44:55 CET 2006


Brian Sutherland wrote:
> On Sat, Jan 07, 2006 at 06:20:42PM +0000, Christian Lück wrote:
>> Hi!
>> 
>> I yust found out how to implement add views for a SQLOS-inheriting
>> content component. Since it might be interisting for others I post it
>> here. If this should be old hat to you, sorry.
>> 
>> The key to get an IAdding view for SQLOS objects running is that you
>> have to leave the z3 standard two step add process. To put it short: You
>> have to rewrite (leave away) the add() method for the add view
>> (inherited from zope.app.form.browser.AddView or
>> zope.formlib.form.AddFormBase).
>> 
>> More detailed:
>> 
>> The standard z3 prozess to add an object to a container is two steps:
>> 1) Creation of the object by calling a factory.
>> 2) Adding this object instance to a container.
>> This is normally handled by a method of the add view called
>> createAndAdd(). createAndAdd() again calls create() for step 1 and then
>> add() for step 2.
>> 

>> 
>> Creating an SQLOS object differs from this standard inasmuch step 2 is
>> not only not recommended (a) but even causes errors (b).
>> 
>> a) not recommended: As a consequence of the current sqlos implementation
>>  all instances of a content component class inheriting from SQLOS go
>> into the same rdb table. => Each container for this content component
>> shows all the instances of this component. Imagine two containers with
>> preconditions set for the same content component, each one will show a
>> set union as its items. - That's why SQLOS objects are not really
>> locateable.
>> Corollar: Instantiating an content object, which inherits from SQLOS,
>> lets this instance show up in each SQLObjectContainer with matching
>> preconditions.
> 
> Yes, though it is possible to simulate this if every container has a
> unique_id which is stored on the content object itself. There is an
> "Isolated" container implementation in the source which does this.
> 

Cool, I did know that one.

> There is no corresponding SQLOS implementation as the obvious
> implementation is a multiple join and inheritance of 2 SQLObject
> related classes was too risky.
> 



>> 
>> Proposal / Desiderata:
>> 
>> - sqlos.container.SQLObjectContainer should be reimplemented to get
>> standard add views ( = views for zope.app.container.interfaces.IAdding )
>> going. Idea (but not more): Reimplement the methods of
>> SQLContainerObjects which are called by the magic '+' ( = an
>> implementation of IAdding), which is called by the standard z3 add()
>> methods in zope.app.form.browser.add.AddView or
>> zope.formlib.form.AddFormBase.
> 
> There is a testbrowser functional test in ftests/adding.txt which
> actually tests the IAdding for a sampleperson. With the standard
> browser:addform directive. A first step might be to extend that test so
> that it fails.

Whenever I try to add an item with a <browser:addForm> view, I get the
follwing exception:

2006-01-20T22:20:21 ERROR txn.-1236755536 Failed to abort resource
manager: <transaction._transaction.DataManagerAdapter object at 0xb52ae6cc>
Traceback (most recent call last):
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/transaction/_transaction.py",
line 507, in abort
    rm.abort(self)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/transaction/_transaction.py",
line 634, in abort
    self._datamanager.abort(transaction)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/app/rdb/__init__.py",
line 445, in abort
    self._dbconn.rollback()
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/app/rdb/__init__.py",
line 391, in rollback
    self.conn.rollback()
NotSupportedError: (1196, "Warning:  Some non-transactionalchanged
tables couldn't be rolled back")
Traceback (most recent call last):
  File "/usr/local/lib/python2.4/threading.py", line 422, in run
    self.__target(*self.__args, **self.__kwargs)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/twisted/python/threadpool.py",
line 149, in _worker
    context.call(ctx, function, *args, **kwargs)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/twisted/python/context.py",
line 59, in callWithContext
    return self.currentContext().callWithContext(ctx, func,*args, **kw)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/twisted/python/context.py",
line 37, in callWithContext
    return func(*args,**kw)
--- <exception caught here> ---
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/twisted/web2/wsgi.py",
line 139, in run
    result = self.application(self.environment, self.startWSGIResponse)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/app/wsgi/__init__.py",
line 54, in __call__
    request = publish(request, handle_errors=handle_errors)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/publisher/publish.py",
line 146, in publish
    publication.handleException(
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/app/publication/zopepublication.py",
line 243, in handleException
    transaction.abort()
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/transaction/_manager.py",
line 107, in abort
    return self.get().abort(sub, deprecation_wng=False)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/transaction/_transaction.py",
line 507, in abort
    rm.abort(self)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/transaction/_transaction.py",
line 634, in abort
    self._datamanager.abort(transaction)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/app/rdb/__init__.py",
line 445, in abort
    self._dbconn.rollback()
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/app/rdb/__init__.py",
line 391, in rollback
    self.conn.rollback()
_mysql_exceptions.NotSupportedError: (1196, "Warning:
Somenon-transactional changed tables couldn't be rolled back")
127.0.0.1 - - [20/Jan/2006:22:20:21 +0100] "POST
/persons/+/AddPerson.html%3D HTTP/1.1" 500 201
"http://localhost:8080/persons/+/AddPerson.html=" "Mozilla/5.0 (X11; U;
Linux i686;de-DE; rv:1.7.10) Gecko/20050925 Firefox/1.0.4 (Debian
package 1.0.4-2sarge5)"
127.0.0.1 - - [20/Jan/2006:22:20:21 +0100] "GET /favicon.ico HTTP/1.1"
404 4133 "-" "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.10)
Gecko/20050925 Firefox/1.0.4 (Debian package 1.0.4-2sarge5)"


To avoid this, I wrote a view class for my add-view. There I override
the add() method which is inherited from
zope.app.form.browser.add.AddView. It calls the add() method of
the context, which - if I'm not totally wrong - should implemet IAdding.

from zope.app.form.browser.add import AddView

class PersonAddView(AddView):

    __used_for__ = IPerson

    def add(self, content):
        """In sqlos we yust intantiate an object and then it appears
        in the container, but we don't really add an object to a container.
        So we override this method here."""
        return content


Its Registration:

  <addform
      schema="sqlosperson.interfaces.IPerson"
      content_factory="sqlosperson.person.Person"
      class=".person.PersonAddView"
      name="AddPerson.html"
      label="Add Person"
      permission="zope.ManageContent"
      />

But if sqlos wants to make it easy to plug a rdb instead of ZODB, then
having to change all your add views is not acceptable..
I thought about rewriting __setitem()__ and __getitem()__
for the container class - but as far as I see, it's yust coded the way I
was thinking of. Well I really don't have an idea..

Regards,
Christian



More information about the z3-sqlos mailing list