=========================== Erstellen eigener Formulare =========================== Um ein eigenes Formular zu erstellen, erzeugen wir zunächst ein Page Template ``registrationreport`` in ``src/vs.registration/vs/registration/browser/`` mit folgendem Inhalt::
Show changes in the the last days.
Dabei wird das ``action``-Attribut dynamisch generiert um zu gewährleisten, dass immer dasselbe Formular im selben Kontext aufgerufen wird. **Anmerkung 1:** Würde ein Skin-Template verwendet, müsste statt der Variablen ``${view/__name__}`` die Variable ``${template/getId}`` verwendet werden. Das Formular wird verarbeitet, wenn der View in ``registrationreport.py`` mit der ``__call__()``-Methode aufgerufen wird:: template = ViewPageTemplateFile('registrationreport.pt') def __call__(self): # Hide the editable-border self.request.set('disable_border', True) # The number for days with a silent fallback on the default # if the input is invalid. try: self.days = int(self.request.get('days', 7)) except ValueError: self.days = 7 return self.template() **Anmerkung 2:** Falls eine Anfrage nicht nur auf den View selbst zugreifen muss, ist ``self.request`` nicht mehr ausreichend; stattdessen ist dann die Anfrage zu akquirieren mit ``request = context.REQUEST``. **Anmerkung 3:** Für ``HTTP POST``-Anfragen sollte statt ``self.request`` ``self.request.form`` angegeben werden, da dies versehentlich akzeptierte Variablen verhindert. Die anderen Methoden des Views untersuchen ``self.days`` zum Erstellen der Such-Parameter:: def recently_modified_registrants(self): context = aq_inner(self.context) catalog = getToolByName(context, 'portal_catalog') results = [] for r in catalog(object_provides=IRegistrant.__identifier__, modified=dict(query=self.modified_after(), range='min'), sort_on='modified', sort_order='reverse',): results.append(dict(url=r.getURL(), title=r.Title, description=r.Description, modified=self.localize(r.modified))) return results def localize(self, time): return self._time_localizer()(time, None, aq_inner(self.context), domain='plonelocales') def modified_after(self): return DateTime() - self.days @memoize def _time_localizer(self): context = aq_inner(self.context) translation_service = getToolByName(context, 'translation_service') Mehrere ``submit``-Tasten ========================= Sind für ein Formular mehrere Tasten verfügbar, muss überprüft werden, welche der Tasten gedrückt wurde und welche Aktion hierfür auszuführen ist. Wie dies geschieht, können Sie sich z.B. in ``plone.app.workflow.browser.sharing`` anschauen:: In ``sharing.py`` wird dann zunächst überprüft, welche Taste gedrückt wurde. Dabei ist zu beachten, dass Web-Browser immer nur den Wert für ``name`` derjenigen Taste senden, auf die geklickt wurde. Anschließend wird die entsprechende Aktion zuzuweisen:: class SharingView(BrowserView): # Actions template = ViewPageTemplateFile('sharing.pt') def __call__(self): """Perform the update and redirect if necessary, or render the page """ postback = True form = self.request.form submitted = form.get('form.submitted', False) save_button = form.get('form.button.Save', None) is not None cancel_button = form.get('form.button.Cancel', None) is not None if submitted and not cancel_button: if not self.request.get('REQUEST_METHOD','GET') == 'POST': raise Forbidden # Update the acquire-roles setting inherit = bool(form.get('inherit', False)) self.update_inherit(inherit) # Update settings for users and groups entries = form.get('entries', []) roles = [r['id'] for r in self.roles()] settings = [] for entry in entries: settings.append( dict(id = entry['id'], type = entry['type'], roles = [r for r in roles if entry.get('role_%s' % r, False)])) if settings: self.update_role_settings(settings) # Other buttons return to the sharing page if cancel_button: postback = False if postback: return self.template() else: context_state = self.context.restrictedTraverse("@@plone_context_state") url = context_state.view_url() self.request.response.redirect(url) Eingabekonverter ================ Aus dem ``sharing.pt``-*Page Template* lässt sich auch ablesen, wie Formularfelder berechnet werden können:: Dies wird dargestellt in einer ``tal:repeat``-Schleife. Wird das Formular abgeschickt, wird die Variable ``entries`` mit einer Liste von Wörterbüchern aus den Schlüsselwörtern ``"id"`` und ``"type"`` übertragen. Ein Überblick über alle verfügbaren Konverter erhalten Sie hier: +------------------------+------------------------------------------------+--------------------------------+ | Konverter | Beispiel | Anmerkung | +========================+================================================+================================+ | ``boolean``, | :: | Wandelt die Variable in den | | | | zugehörigen Python-Typ um, | | ``int``, | | Zeilenumbrüchen entsprechend | | | | der Server-Plattform | +------------------------+------------------------------------------------+--------------------------------+ | ``list``, | :: | Erstellt eine Liste oder ein | | | | Tuple aus mehreren Feldern | | ``tuple`` | | in eine Liste um | +------------------------+------------------------------------------------+--------------------------------+ | ``record``, | :: | Erstellt ein Wörterbuch | | | | (``record``) oder eine Liste | | ``records`` | | (``records``). Der Name vor | | | | ``.`` ist der Variablenname, | | | | der Name danach der | | | | Schlüssel. | +------------------------+------------------------------------------------+--------------------------------+ | ``required`` | :: | Gibt eine Fehlermeldung aus | | | | wenn das Feld nicht ausgefüllt | | | | | | | | | +------------------------+------------------------------------------------+--------------------------------+ | ``ignore_empty`` | :: | Die Variable wird bei einem | | | | Request nicht angegeben wenn | | | | | | | | Dieser Konverter kann mit | | | | anderen kombiniert werden. | +------------------------+------------------------------------------------+--------------------------------+ | ``default`` | :: | Standardwert, falls in keinem | | | | Feld mit demselben Namen ein | | | | Dies ist vor allem für | | | | keine Angabe gemacht wurde. | | | | | | | | Dieser Konverter kann mit | | | | anderen kombiniert werden. | +------------------------+------------------------------------------------+--------------------------------+