Benutzer-Werkzeuge

Webseiten-Werkzeuge


python:grok_and_zope.app.undo

What: undo transactions in grok

Problem: zope.app.undo does not work with ZODB-3.10 and grok-1.10.3

Solutions (all these are workarounds, use them at your own risk):

as result of adding zope.app.undo to setup.py following error appears:

ConfigurationError: ('Unknown directive', u'http://namespaces.zope.org/browser', u'menuItem')

edit

zope.app.undo-3.5.0-py2.7.egg/zope/app/undo/configure.zcml

and delete the menuItem-Sections; menuItem is used bei ZMI and implemented bei zc.forms or other but not by zope.formlib; I use zope.formlib in grok apps

2. ZODB has changed the api

Error after submit the transaction ID's:

"Duplicate tpc_begin calls for same transaction"

The undo API has changed with ZODB 3.10. As noted in the changelog:

      
      "The API for undoing multiple transactions has changed. To undo
      multiple transactions in a single transaction, pass a list of
      transaction identifiers to a database's undoMultiple method. Calling a
      database's undo method multiple times in the same transaction now
      raises an exception."
      
      Your code calls undo multiple times, and needs to be changed accordingly.

edit in

zope.app.undo-3.5.0-py2.7.egg/zope/app/undo/__init__.py

the last def:

old:

    def _undo(self, ids):
 
        for id in ids:
            self.__db.undo(id)
        transaction.get().setExtendedInfo('undo', True)

new:

    def _undo(self, ids):
 
        self.__db.undoMultiple(ids)
        transaction.get().setExtendedInfo('undo', True)

Demo grok View

from zope.app.undo import ZODBUndoManager
from zope.app.undo.interfaces import IUndoManager
from zope.component import getUtility
from zope.interface import Interface
 
class Undo(grok.View):
  grok.context(Interface)
  grok.require('zope.Public')
 
 
  def getPrincipalTransactions(self, first=0, last=-20, showall=False):
        context = None
        if not showall:
            context = self.context
        undo = getUtility(IUndoManager)
        return undo.getPrincipalTransactions(self.request.principal, context,
                                             first, last)

and the undo.pt:

<html i18n:domain="zope">
<body>
 
<form action="@@undoPrincipalTransactions.html" method="post">
 
<div>
  <tal:var define="global batch_size python:10;
                   global first      python:int(request.get('first', 0));
                   global showall    python:bool(request.get('showall', False))"
                   />
</div>
 
<div>
  <span tal:condition="showall">
    <p>
      <span i18n:translate="">You are looking at transactions
      regardless of location.</span> <a href="?"
      i18n:translate="">View only transactions in this location</a>.
    </p>
  </span>
 
  <span tal:condition="not:showall">
    <p>
      <span i18n:translate="">You are looking only at transactions
      from this location.</span> <a href="?showall=true"
      i18n:translate="">View transactions regardless of location</a>.
    </p>
  </span>
</div>
 
<div>
    <table style="width: 100%; border: none;">
 
      <tr>
        <th></th>
        <th i18n:translate="heading-location">Location</th>
        <th i18n:translate="heading-request-info">Request info</th>
        <th i18n:translate="heading-principal">Principal</th>
        <th i18n:translate="heading-date">Date</th>
        <th i18n:translate="heading-description">Description</th>
      </tr>
 
      <tal:block repeat="item python:view.getPrincipalTransactions(first=first, 
                                                                   last=-batch_size, 
                                                                   showall=showall)">
      <tr tal:attributes="class python:repeat['item'].odd() and
                                       'content odd' or 'content even'">
 
        <td width="16">
          <input type="checkbox" name="ids:list" value="-1"
                 tal:attributes="value item/id" />
        </td>
 
    <td tal:define="location item/location | nothing">
          <tal:location replace="location" />
          <tal:if condition="not:location"
                  i18n:translate="label-not-available">not available</tal:if>
        </td>
 
        <td>
          <tal:request_info replace="item/request_type | nothing" /><br />
          <tal:request_info replace="item/request_info | nothing" />
          <tal:if condition="python:not item.get('request_type', '') and
                                    not item.get('request_info', '')"
                  i18n:translate="label-not-available">not available</tal:if>
        </td>
 
        <td>
          <tal:principal replace="item/principal/id | nothing" />
          <tal:if condition="not:exists:item/principal/id"
                  i18n:translate="label-not-available">not available</tal:if>
        </td>
 
        <td tal:define="formatter python:request.locale.dates.getFormatter(
                                         'dateTime', 'medium')"
            tal:content="python:formatter.format(item['datetime'])">
        </td>
 
        <td>
          <tal:description i18n:translate=""
            replace="item/description | nothing" />
          <tal:if condition="not:item/description"
                  i18n:translate="label-not-available">not available</tal:if>
        </td>
      </tr>
      </tal:block>
 
    </table>
</div>
 
<p>
  <a tal:define="showall python:showall and '&showall=true' or ''"
     tal:attributes="href python:'?first=%s%s'%(first+batch_size, showall)">
    &lt;&lt;&lt;
    <tal:text i18n:translate="">
      View <tal:num replace="batch_size" i18n:name="number" />
      earlier transactions
    </tal:text>
  </a>
</p>
 
<p>
  <a tal:define="showall python:showall and '&showall=true' or ''"
     tal:condition="python:first >= batch_size"
     tal:attributes="href python:'?first=%s%s'%(first-batch_size, showall)">
    <tal:text i18n:translate="">
      View <tal:num tal:replace="batch_size" i18n:name="number" />
      later transactions
    </tal:text>
    &gt;&gt;&gt;
  </a>
</p>
 
<p>
  <input type="submit" value="Undo"
         i18n:attributes="value undo-button" />
</p>
 
<form>
 
</body>
</html>
python/grok_and_zope.app.undo.txt · Zuletzt geändert: 2012/09/12 14:08 von 2007