25. Convertir charlas en eventos

Se nos olvidó algo: Una lista de los tipos de contenidos talks es especialmente excelente si usted puede ordenarlo por sus preferencias. Pero si un visitante decide que quiere ver una charla que necesita saber cuándo va a tener lugar.

Necesitamos un programa y para ello necesitamos almacenar la información de cuando una charla va a suceder.

Afortunadamente el tipo Evento es basado en comportamiento reusable desde el paquete plone.app.event.

En este capítulo vamos a tratar:

  • Habilitar este comportamiento para las charlas.

  • Escribir un paso de actualización (upgrade step) para evitar un error en el paquete plone.app.event.

  • Mostrar la fecha en la vista talkview.

Primero nosotros habilitamos el comportamiento IEventBasic para los tipos de contenidos talksen el archivo profiles/default/types/talk.xml, agregando el siguiente código XML:

1
2
3
4
5
6
7
<property name="behaviors">
  <element value="plone.app.dexterity.behaviors.metadata.IDublinCore"/>
  <element value="plone.app.content.interfaces.INameFromTitle"/>
  <element value="ploneconf.site.behavior.social.ISocial"/>
  <element value="ploneconf.site.interfaces.ITalk"/>
  <element value="plone.app.event.dx.behaviors.IEventBasic"/>
</property>

Después activamos el comportamiento manualmente o vuelta a instalar el complemento, podríamos añadir nuevos tipos de contenidos talks con el nuevo campo de start y end.

Pero debido a un error en plone.app.event no se espera que los objetos existentes obtengan el comportamiento. Desde los tipos de contenidos existentes no tienen valores en los campos start y end nos encontraremos con un traceback en línea de validación cuando editamos estos campos. Para solucionar esto creamos un paso de actualización que establece alguna una fecha inicial.

Registrar el nuevo paso de actualización (upgrade step) en el archivo upgrades.zcml, agregando el siguiente código ZCML:

1
2
3
4
5
6
7
8
9
<genericsetup:upgradeStep
  title="Add event-behavior to talks"
  description=""
  source="1001"
  destination="1002"
  handler="ploneconf.site.upgrades.turn_talks_to_events"
  sortkey="1"
  profile="ploneconf.site:default"
  />

Cambiar la versión del perfil a 1002 en el archivo profiles/default/metadata.xml

Escribir el paso de actualización (upgrade sted) en el archivo upgrades.py, agregando el siguiente código Python:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -*- coding: UTF-8 -*-
from plone import api

import datetime
import logging
import pytz


default_profile = 'profile-ploneconf.site:default'

logger = logging.getLogger('ploneconf.site')

def upgrade_site(setup):
    setup.runImportStepFromProfile(default_profile, 'typeinfo')
    catalog = api.portal.get_tool('portal_catalog')
    portal = api.portal.get()
    if 'the-event' not in portal:
        theevent = api.content.create(
            container=portal,
            type='Folder',
            id='the-event',
            title='The event')
    else:
        theevent = portal['the-event']
    if 'talks' not in theevent:
        talks = api.content.create(
            container=theevent,
            type='Folder',
            id='talks',
            title='Talks')
    else:
        talks = theevent['talks']
    talks_url = talks.absolute_url()
    brains = catalog(portal_type='talk')
    for brain in brains:
        if talks_url in brain.getURL():
            continue
        obj = brain.getObject()
        logger.info('Moving %s to %s' % (obj.absolute_url(), talks.absolute_url()))
        api.content.move(
            source=obj,
            target=talks,
            safe_id=True)

def turn_talks_to_events(setup):
    """Set a start- and end-date for old events to work around a
    bug in plone.app.event 1.1.1
    """
    api.portal.set_registry_record(
        'plone.app.event.portal_timezone',
        'Europe/London')
    setup.runImportStepFromProfile(default_profile, 'typeinfo')

    tz = pytz.timezone("Europe/London")
    now = tz.localize(datetime.datetime.now())
    date = now + datetime.timedelta(days=30)
    date = date.replace(minute=0, second=0, microsecond=0)

    catalog = api.portal.get_tool('portal_catalog')
    brains = catalog(portal_type='talk')
    for brain in brains:
        obj = brain.getObject()
        if not getattr(obj, 'start', False):
            obj.start = obj.end = date
            obj.timezone = "Europe/London"

Después que ejecutamos el paso de actualización ahora podemos añadir un tiempo para los existentes eventos. Para mostrar estos reutilizamos una vista de resumen para los eventos por defecto como se documenta en http://ploneappevent.readthedocs.io/en/latest/development.html#reusing-the-event-summary-view-to-list-basic-event-information

Edite el archivo browser/templates/talkview.pt, agregando el siguiente código ZPT:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
      metal:use-macro="context/main_template/macros/master"
      i18n:domain="ploneconf.site">
<body>
    <metal:content-core fill-slot="content-core" tal:define="widgets view/w">

        <tal:eventsummary replace="structure context/@@event_summary"/>

        <p>
            <span tal:content="context/type_of_talk">
                Talk
            </span>
            suitable for
            <span tal:replace="structure widgets/audience/render">
                Audience
            </span>
        </p>

        <div tal:content="structure widgets/details/render">
            Details
        </div>

        <div class="newsImageContainer">
            <img tal:condition="python:getattr(context, 'image', None)"
                 tal:attributes="src string:${context/absolute_url}/@@images/image/thumb" />
        </div>

        <div>
            <a class="email-link" tal:attributes="href string:mailto:${context/email}">
                <strong tal:content="context/speaker">
                    Jane Doe
                </strong>
            </a>
            <div tal:content="structure widgets/speaker_biography/render">
                Biography
            </div>
        </div>

    </metal:content-core>
</body>
</html>