segunda-feira, 18 de janeiro de 2010

Criando um Objeto Usando Generic Plone Content Via Python

Como eu faço para criar um objeto que é um AT Content, ou um objeto que o tipo foi feito com Generic Plone Content diretamente do meu código python? A idéia desse código é mostrar exatamente isso.

Esse manual foi caradepaumente copiado de um tutorial em inglês. Porque eu fiz isso? Porque passei horas procurando por "Generic Plone Content" e não achei quase nada. Esse tutorial serve para você criar um conteúdo gerado via Archetypes ou Generic, porque no final das contas, o Generic usa Archetypes. Então, vamos ao que interessa. Leia atentamente, pricipalmente a próxima linha.

E ai? Leu a linha de cima? Pois é, ela só serve para me beneficiar. Vamos ao que insteressa.

Normalmente, criamos conteúdo usando "here". Que é o nosso contexto atual. Isso criaria um objeto na pasta em que estamos. E é isso que fazemos via Plone. Navegamos até uma pasta e criamos o conteúdo. Em Python, chamamos isso de "context" em um script ou Page Template, ou "self" em um produto. Aqui, usaremos a variável "container". Porque o container vai conter o que queremos. :_)

Então teremos "self" ou "context", dependendo da situação. Vou assumir context daqui pra frente.

container = context

Mas e se você quiser que o container seja uma outra pasta? Então você faz:

container = context.nomeDaPasta #A pasta ja deve existir

reparem que acima, nomeDaPasta será hard coded, ou podemos fazer:

#Retorna none caso nao exista a pasta
container = getattr(context, 'nomeDaPasta', None)

Nesse exemplo, o nome da pasta é uma string. Ou seja, pode ser parametrizado. Agora, muita atenção para a linha verdade logo abaixo. Ela é importante (para mim).

Você também pode fazer deste jeito:

container = context['nomeDaPasta']

Você não fica restrito a um nível, pode descer o quanto achar conveniente:

container = context.pasta1.subPasta1

Da forma abaixo você busca a pasta pai em relação ao contexto atual

container = context.aq_inner.aq_parent

Existe também a opção de encontrar uma pasta utilizando a raiz do portal:

from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, 'portal_url')
portal = urltool.getPortalObject()
container = portal.animais.cachorros.retrievers

Agora que você sabe como escolher o container, você pode criar seu objeto nele.
Veja o comandinho abaixo.

id = "nowHearThis"
container.invokeFactory(type_name="News Item", id=id)

Você precisa atribuir um ID ao objeto e dizer qual é o tipo de conteudo: type_name="seu tipo"

Segundo o autor do tutorial, invokeFactory vai obedecer restrições difinidas no tipo de conteúdo, como as opções de implicitly addable e filtros. Pode ser que você tenha definido que um tipo de conteúdo não é adicionavel pelo usuário. E mesmo assim você pode querer criá-lo via script. Veja abaixo

typestool = getToolByName(context, 'portal_types')
typestool.constructContent(type_name="News Item", container=container, id=id)

O conteúdo já foi criado. E agora? Você pode inserir mais informações no objeto da seguinte forma: primeiro, pegamos o objeto.

obj = container[id]

Depois, setamos uma informação:

obj.setTitle("Now Hear This!")

Em seguida, você pode reindexar o objeto no catálogo da seguinte forma:

obj.reindexObject()