Ferramentas Pessoais
Acessar

Ir para o conteúdo. | Ir para a navegação

Navegação

Exercícios

Exercício 3: Instalando o pacote

Vamos utilizar um esqueleto do Zopeskel chamado dexterity para gerar o nosso pacote, em src:

../bin/zopeskel dexterity treinamento.content

(Aperte [Enter] para todas as perguntas)

Adicione o novo pacote ao buildout.

Rode o buildout (./bin/buildout -c develo.cfg)

Reinicie a instância e verifique se o novo pacote já está disponível para ser instalado.

Exercício 4: Mudando o título do seu pacote

Na raiz do seu pacote (treinamento.content/treinamento/content, edite o arquivo configure.zcml:

title="Example Dexterity Product” 
title=“Projeto Alfa – Tipos”
description="Extension profile for Example Dexterity Product”
description=“Tipos de conteúdo Dexterity para o Projeto Alfa”

Reinicie a instância e verifique as modificações.

Exercício 5: Criando tipos de conteúdo

Dentro da pasta $INSTANCE_HOME/src/treinamento.content:

./../../bin/paster addcontent dexterity_content
Criaremos dois tipos:
  • Palestra
    • Name: Palestra
    • Description: Uma palestra em uma conferencia
    • Global-allow: False
  • Programa:
    • Name: Programa
    • Description: A programacao de uma conferencia
    • Folderish: True
    • Global-allow: True

Exercício 6: O Schema de Programa

Neste exercício vamos implementar o schema de Programa. No arquivo programa.py:

from treinamento.content import MessageFactory as _
from five import grok
from plone.app.textfield import RichText
from plone.supermodel import model
from zope import schema


class IPrograma(model.Schema):
        """A programacao de uma conferencia
     """

    title = schema.TextLine(
        title=_(u"Nome do programa"),
    )

    description = schema.Text(
        title=_(u"Sumário do programa"),
    )

        start = schema.Datetime(
                    title=_(u"Data de Início"),
                    required=False,
            )

        end = schema.Datetime(
                    title=_(u"Data de Término"),
                    required=False,
            )

        details = RichText(
                    title=_(u"Detalhes"),
                    description=_(u"Detalhes sobre o programa"),
                    required=False,
            )

Exercício 7: O Schema de Palestra

Utilizando o que você aprendeu no exercício anterior, crie os três campos a seguir:

Título (title) 

Sumário da palestra (description)

Detalhes da palestra (details) (required=False)

Solução:

from treinamento.content import MessageFactory as _
from five import grok
from plone.app.textfield import RichText
from plone.supermodel import model
from zope import schema


class IPalestra(model.Schema):
            """A conference session. Sessions are managed inside Programs.
     """

            title = schema.TextLine(
                        title=_(u"Title"),
                        description=_(u"Session title"),
                )

            description = schema.Text(
                        title=_(u"Session summary"),
                )

            details = RichText(
                        title=_(u"Session details"),
                        required=False
                )

Exercício 8 e 9

Estão nos slides.

Exercício 10: Criando o tipo de conteúdo Palestrante

Dentro da pasta $INSTANCE_HOME/src/treinamento.content:

./../../bin/paster addcontent dexterity_content
  • Palestrante:
    • Name: Palestrante
    • Description: Uma pessoa apresentando uma palestra na conferencia.
    • Folderish: False
    • Global-allow: True
    • Allow-discussion: False

Exercício 11: Tipo Palestrante TTW

Utilizando a interface Web para criação de tipos dexterity, vamos criar um tipo chamado Palestrante TTW:

Desative o behavior "Metadados Dublin Core".

Campos

  • Nome -> (title) -> TextLine
  • Sumário -> (description) -> Text
  • Biografia -> (biografia) -> required=False -> RichText
  • Foto -> (foto) -> required=False -> Image 

Exercício 12: Migrando para o sistema de arquivos

Utilize o botão "XML Field Model" para ver o XML do tipo Palestrante TTW.

Copie o conteúdo do arquivo mostrado e coloque no arquivo models/palestrante.xml.

Remova o behavior "IBasic" em profiles/default/types/palestrante.xml. (já temos nosso title e description)

Reinicie sua instância e verifique se os campos estão disponíveis no tipo Palestrante do sistema de arquivos.

Remova o tipo Palestrante TTW, não precisaremos mais dele.

Exercício 13: Criando a visualização padrão para Programa

Lembrando: Uma view é composta por uma classe Python e um template. Nossa classe Python está em programa.py e o template em programa_templates/.

A classe Python:

class View(grok.View):
    grok.context(IPrograma)
        grok.require('zope2.View')

        def palestras(self):
                """Retorna uma pesquisa no catalogo com as palestras a serem mostradas
         """

                context = aq_inner(self.context)
                catalog = getToolByName(context, 'portal_catalog')

                return catalog(Type='Palestra',
                                              path='/'.join(context.getPhysicalPath()),
                                              sort_on='sortable_title')

O template programa_templates/view.pt:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
    xmlns:tal="http://xml.zope.org/namespaces/tal"
    xmlns:metal="http://xml.zope.org/namespaces/metal"
    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
    lang="en"
    metal:use-macro="context/main_template/macros/master"
    i18n:domain="treinamento.content"> <body> <metal:main fill-slot="content-core">  
    <div class="discreet">         <tal:block condition="context/start">             <span i18n:translate="label_from">From:</span>             <span tal:content="python:context.start.strftime('%d/%m/%Y %H:%M')" />         </tal:block>         <tal:block condition="context/end">             <span i18n:translate="label_to">To:</span>             <span tal:content="python:context.end.strftime('%d/%m/%Y %H:%M')" />         </tal:block>     </div>
    <div tal:content="structure context/details/output" />     <h2 i18n:translate="heading_sessions">Palestras</h2>     <dl>         <tal:block repeat="palestra view/palestras">             <dt>                 <a tal:attributes="href palestra/getURL"                    tal:content="palestra/Title" />             </dt>             <dd tal:content="palestra/Description" />         </tal:block>     </dl>
</metal:main> </body> </html>

Exercício 14: Criando a visualização padrão para Palestra

A classe Python (palestra.py):

class View(dexterity.DisplayForm):
    grok.context(IPalestra)
    grok.require('zope2.View')

O template palestra_templates/view.pt:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
    xmlns:tal="http://xml.zope.org/namespaces/tal"
    xmlns:metal="http://xml.zope.org/namespaces/metal"
    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
    lang="en"
    metal:use-macro="context/main_template/macros/master"
    i18n:domain="treinamento.content"> <body> <metal:main fill-slot="content-core">  

    <div tal:content="struture view/w/details/render" />
 
</metal:main> </body> </html>

Exercício 15: Criando a visualização padrão para Palestrante

A classe Python (palestrante.py):

class View(grok.View):
    grok.context(IPalestrante)
        grok.require('zope2.View')

No arquivo palestrante_templates/view.pt

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
    xmlns:tal="http://xml.zope.org/namespaces/tal"
    xmlns:metal="http://xml.zope.org/namespaces/metal"
    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
    lang="en"
    metal:use-macro="context/main_template/macros/master"
    i18n:domain="treinamento.content"> <body> <metal:main fill-slot="content-core">  

    <div tal:content="structure context/biografia/output" />
 
</metal:main> </body> </html>

Exercício 16: Valores Padrão

Vamos configurar valores padrão para os campos de data de Início e Término do programa para 1 semana no futuro e 10 dias no futuro, respectivamente.

import datetime

@form.default_value
(field=IPrograma['start']) def startDefaultValue(data):     return datetime.datetime.today() + datetime.timedelta(7) @form.default_value(field=IPrograma['end']) def endDefaultValue(data):     return datetime.datetime.today() + datetime.timedelta(10)

Exercício 17: Validadores

Vamos criar um validador para o campo description de programa.py:


def
check_summary(value):     return len(value) > 2

No campo description:

description = schema.Text(
    title=_(u"Program summary"),
    constraint=check_summary,
)

Exercício 18: Vocabulário

Importe o vocabulário de usuários do Plone:

from plone.app.vocabularies import Users

Vamos adicionar um campo chamado organizador em programa.py:

organizador = schema.Choice(
    title=_(u"Organizador"),
    vocabulary="plone.app.vocabularies.Users",
    required=False,
        )

Exercício 19: Eventos

Vamos criar uma função que será executada toda vez que criarmos um Palestrante. Essa função irá tentar encontrar usuários com nomes parecidos ao Palestrante e enviar a esses usuários um e-mail.

No arquivo palestrante.py, vamos fazer os imports:

from zope.lifecycleevent.interfaces import IObjectAddedEvent
from Products.CMFCore.utils import getToolByName

E agora a função que será chamada, abaixo da definição do schema:

@grok.subscribe(IPalestrante, IObjectAddedEvent)
def notifyUser(palestrante, event):
    acl_users = getToolByName(palestrante, 'acl_users')
        mail_host = getToolByName(palestrante, 'MailHost')
        portal_url = getToolByName(palestrante, 'portal_url')

        portal = portal_url.getPortalObject()
        sender = portal.getProperty('email_from_address')

        if not sender:
                return

        subject = "Is this you?"
        message = "A presenter called %s was added here %s" % (palestrante.title, palestrante.absolute_url(),)

        matching_users = acl_users.searchUsers(fullname=palestrante.title)
        for user_info in matching_users:
                email = user_info.get('email', None)
                if email is not None:
                        mail_host.secureSend(message, email, sender, subject)