Guia de Sobrevivência Urbana: Fórum Internacional de Software Livre

Vi esse post e achei muito interressante para quem vai para o FISL!

“Na próxima Quarta-Feira inicia a 10a. edição do Fórum Internacional de Software Livre (FISL), o maior evento de software livre do Brasil. Pensando nos milhares de brasileiros que virão para a capital gaúcha, muitos pela primeira vez, criei este ‚Äúguia‚Äù que com bom humor da várias dicas para o evento e estadia em Porto Alegre.” [referência: incerteza.org]

Rumo ao FISL

Passagem comprada, hotel reservado e inscrição confirmada. Agora só falta chegar lá em POA.

Estou indo pela primeria vez participar do evento que considerado a Meca do desenvolvimento de software livre. Com presenças confirmadas de Richard Stallman, Peter Sunde Kolmisoppi (The Pirate Bay), Jon “Maddog” Hall e vários outros entusiastas do software livre do Brasil e do mundo.

Quem quiser ir ainda da tempo, pois as inscrições pelo site acabam dia 18 e a as passagens de avião estão em conta. Essa 10¬™ edição do FISL promete bastante, em breve muitas fotos do evento.

Saiu o Ubuntu 9.04

A partir de hoje já esta disponível para download a versão 9.04 do Ubuntu. Apelidada de Jaunty Jackalope, a nova versão atualiza grande parte dos pacotes a 8.10 e traz novidades interessantes, entre elas estão:

  • Gnome 2.26
  • Brasero 2.26.0
  • Melhor manuseio de múltiplos monitores
  • X.org server 1.6
  • Novo estilo para notificações
  • Kernel 2.6.28
  • Suporte a Ext4

Para fazer o download acesse o site http://www.ubuntu.com e clique em “Get Ubuntu”, ou então clique aqui.

Nesse momento estou atualizando o meu desktop do trabalho, são exatos 1359 arquivos para baixar, e como hoje a conexão não é das melhores, depois que terminar a atualização posto mais detalhes sobre o que eu achei.

Mais informações sobre as novidades da versão 9.04 acesse: https://wiki.ubuntu.com/JauntyJackalope/TechnicalOverview

Alagoas Digital

Semana que vem tem início o Alagoas Digital, um evento de grande porte de tecnologia no Estado de Alagoas. Num esforço conjunto do ITEC com várias secretarias do estado alagoano, o evento reunirá grandes nomes como Silvio Meira e Henrique Miorelli.

Nos dias 6 e 7 de abril, estarei ministrando, ao lado de Carlos Jean, um mini-curso sobre Desenvolvimento Web em ambinete Zope/Plone. Será um mini-curso básico onde mostraremos entre outras coisas o uso do ArchGenXML para criação rápida de produtos Plone.

Mais informações sobre o Alagoas Digital acesse: http://www.alagoasdigital.com.br

Alagoas Digital

CMS com o django parte 2

Bom mais de um mês depois da primeira parte, finalmente tive tempo para voltar com a segunda parte desse artigo. Como prometido nessa parte vou mostrar mais duas aplicações que facilitam a nossa vida na construção de um CMS com o django.

django-tinymce

Para quem não conhece o TinyMCE é um poderoso editor WYSIWYG para navegadores web que permite ao usuário editar conteúdo HTML de uma maneira mais amigável. O que o django-tinymce faz é dar opções que facilitam o seu carregamento.

Instalação

Coloque o módulo tinymce no path do python. Vocꬆ pode coloca-lo no diretorio do projeto django ou executar o comando python setup.py install.

Copie o diretorio jscripts/tiny_mce da distribuição do TinyMCE num diretorio chamado js no seu diretório de media. Você pode alterar essa localização em settings.py.

Se você quiser usar algumas das views adicione tinymce na sua lista de aplicações e no URLconf:

settings.py:

INSTALLED_APPS = (
    ...
    'tinymce',
    ...
)

urls.py:

urlpatterns = patterns('',
    ...
    (r'^tinymce/', include('tinymce.urls')),
    ...
)

Utilizando como widget:
Se você usar o widget (recomendado) você precisa adicionar algum código python e possivelmente modificar seu template.
O widget do TinyMCE pode ser habilitado alterando o widget num formfield. Por exemplo, para usar widget para campo content numa flatpage você pode usar o seguinte código:

from django import forms
from django.contrib.flatpages.models import FlatPage
from tinymce.widgets import TinyMCE

class FlatPageForm(ModelForm):
    ...
    content = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
    ...

    class Meta:
        model = FlatPage

O widget requer um link para o código javascript do TinyMCE. Os templates em django.contrib.admin fazem isso automaticamente, então se você só estiver usando tinymce em formulários do admin já está tudo certo. Para seus prórios templates contendo o widget você deve adicionar o seguinte código na tag head do HTML (assumindo que você nomeu seu formulario como form):

<head>
    ...
    {{ form.media }}
</head>

O campo HTMLField

Outra opção seria utilizar o model field HTMLField, ele utiliza o TinyMCE como widget para renderizar o campo. No exemplo abaixo, a admin irá renderizar o campo my_field usando o widget TinyMCE:

from django.db import models
from tinymce import models as tinymce_models

class MyModel(models.Model):
    my_field = tinymce_models.HTMLField()

Em todos os outros aspectos o HTMLField se comporta exatamente como o TextField padrão do Django.

Utilizando numa View

Se você não pode ou não irá modificar o widget num formulário você pode utilizar a view tinymce-js¬† para converter alguns ou todos campos de texto numa página para editores TinyMCE. No template da página, adicione as seguintes linhas na tag head:

<script type="text/javascript" src="{{ MEDIA_URL }}js/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="{% url tinymce-js "NAME" %}"></script>

O argumento NAME permite você criar múltiplas configurações do TinyMCE. Agora crie um template contendo o código javascript de inicialização. Ele deve ser colocado no path de templates como NAME/tinymce_textareas.js ou tinymce/NAME_textareas.js.
Exemplo:

tinyMCE.init({
    mode: "textareas",
    theme: "advanced",
    plugins: "spellchecker,directionality,paste,searchreplace",
    language: "{{ language }}",
    directionality: "{{ directionality }}",
    spellchecker_languages : "{{ spellchecker_languages }}",
    spellchecker_rpc_url : "{{ spellchecker_rpc_url }}"
});

Essas são apenas as opções básicas do django-tinymce, para informações mais detalhadas acesse: http://django-tinymce.googlecode.com/svn/tags/release-1.5/docs/.build/html/index.html

django-compress

Javascript e CSS minificação/compressão pode diminuir bastante o tempo de carga de sites. É importante reduzir o número de requests que são feitos. Menos arquivos significa melhor desempenho. No entanto, quando você desenvolver CSS, e especialmente se você está construindo um grande site, pode ser bom separar as diferentes partes do CSS do site em arquivos diferentes. Também queremos manter o CSS e Javascript em arquivos diferentes ao mesmo tempo que você desenvolva, para fazer depuração mais fácil.

Também é agradável para comentar CSS e Javascript, mas você não quer que o overhead do envio de comentários e espaços em branco para os clientes.

Você também quer ter a certeza de que, muito do conteúdo estático está em cache, tanto quanto possível, no cliente. O ideal é mesmo evitar a “304 Not Modified”, que são retornados quando um cliente solicitou uma coisa que já tenha sido colocada em cache, e não precisa de ser atualizado. Isto pode ser conseguido setando o HTTP Expire header para uma data distante no futuro. Isso irá forçar o navegador para não pedir atualizações para esta URL. No entanto, quando você precisar atualizar os seus arquivos, você precisa lhes dar uma nova URL, e enviar os arquivos atualizados para os clientes.

Estas técnicas são descritas mais em profundidade no Yahoo:

  • http://developer.yahoo.com/performance/rules.html#num_http
  • http://developer.yahoo.com/performance/rules.html#minify
  • http://developer.yahoo.com/performance/rules.html#expires

O django-compress é uma aplicação que irá proporcionar uma maneira fácil e automatizada para a saída de CSS e Javascript comprimidos / minificados. Ela segue o princípio DRY, você configura o seus arquivos CSS e Javascript nas configurações do seu projeto, e esta pronto. Não há necessidade de introduzir os nomes no seu modelo novamente (algumas templatetags cuidam cuidado disso).

Instalação

  1. Pegue o código do svn: svn co http://django-compress.googlecode.com/svn/trunk/ django-compress
    1. Use o script setup.py para instalar: python setup.py install
    2. OU manualmente coloque o diretório compress em algum lugar do seu¬† PYTHONPATH
  2. Adicione ‘compress’ na suas INSTALLED_APPS

Configuração

Em settings você especifica grupos de arquivos para serem comprimidos. A sintaxe básica para especificar grupos de CSS/JavaScript é:

COMPRESS_CSS = {
    'group_one': {
        'source_filenames': ('css/style.css', 'css/foo.css', 'css/bar.css'),
        'output_filename': 'css/one_compressed.css',
        'extra_context': {
            'media': 'screen,projection',
        },
    },
    # other CSS groups goes here
}

COMPRESS_JS = {
    'all': {
        'source_filenames': ('js/jquery-1.2.3.js', 'js/jquery-preload.js', 'js/jquery.pngFix.js',
        'js/my_script.js', 'js/my_other_script.js'),
        'output_filename': 'js/all_compressed.js',
    }
}

Opções de grupos

  • source_filenames é uma tuple com os arquivos a serem comprimidos. Os arquivos são concatenados na ordem que são especificados na tupla. Essa opção é obrigatória.
  • output_filename é o nome do arquivo resultante da compressão. Essa opção é obrigatória.
    extra_context é um dicionário de valores para adicionar no contexto do tempate, quando gerando o HTML para as tags HTML com as templatetags. Essa opção é opcional. Para CSS, se você não especificar extra_context/media, a media padrão exibida será media=”all”.

Outras opções:

  • COMPRESS: Quando COMPRESS é True, CSS e JavaScripts serão concatenado e filtrados. Quando False, os aqruivos fonte serão utilizados. Padrão é not DEBUG (arquivos comprimidos so serão utilizados em modo de produção)
  • COMPRESS_CSS_FILTERS: Uma tuple de filtros para serem aplicados a arquivos CSS. Padrão (‘compress.filters.csstidy.CSSTidyFilter’, ). Note que a configuração padrão neessita do CCSTidy.
  • COMPRESS_JS_FILTERS: Uma tuple de filtros que serão aplicados em arquivos JavaScript. Padrão (‘compress.filters.jsmin.JSMinFilter’,)

Como podemos perceber o django-compress utiliza o CSSTidy para comprimir os arquivos CSS. Porém nem sempre se tem acesso para instalação de pacotes no servidor, e a aplicação não oferece uma alternativa ao CSSTidy. Para resolver isso utilizei o código disponibilizado aqui para criar um filtro simples que somente remove os espaços em branco e os comentários.

Crie um pacote chamado cssmin no __init__.py coloque:

import warnings

warnings.simplefilter('ignore', RuntimeWarning)
from compress.filter_base import FilterBase
from cssmin.cssmin import minimalize 

class CssMinFilter(FilterBase):
    def filter_css(self,css):
        return minimalize(css)

E crie o arquivo cssmin.py e coloque:

import re

# Constants for use in compression level setting.
NONE = 0
SIMPLE = 1
NORMAL = 2
FULL = 3

_REPLACERS = {
    NONE: (None),                           # dummy
    SIMPLE: ((r'\/\*.{4,}?\*\/', ''),       # comment
             (r'\n\s*\n', r"\n"),           # empty new lines
             (r'(^\s*\n)|(\s*\n$)', "")),   # new lines at start or end
    NORMAL: ((r'/\*.{4,}?\*/', ''),         # comments
             (r"\n", ""),                   # delete new lines
             ('[\t ]+', " "),               # change spaces and tabs to one space
             (r'\s?([;:{},+>])\s?', r"\1"), # delete space where it is not needed, change ;} to }
             (r';}', "}"),                  # because semicolon is not needed there
             (r'}', r"}\n")),               # add new line after each rule
    FULL: ((r'\/\*.*?\*\/', ''),            # comments
           (r"\n", ""),                     # delete new lines
           (r'[\t ]+', " "),                # change spaces and tabs to one space
           (r'\s?([;:{},+>])\s?', r"\1"),   # delete space where it is not needed, change ;} to }
           (r';}', "}")),                   # because semicolon is not needed there
}

class CssMin:
    def __init__(self, level=FULL):
        self.level = level

    def compress(self, css):
        """Tries to minimize the length of CSS code passed as parameter. Returns string."""
        css = css.replace("\r\n", "\n") # get rid of Windows line endings, if they exist
        for rule in _REPLACERS[self.level]:
            css = re.compile(rule[0], re.MULTILINE|re.UNICODE|re.DOTALL).sub(rule[1], css)
       return css

def minimalize(css, level=NORMAL):
    """Compress css using level method and return new css as a string."""
    return CssMin(level).compress(css)

if __name__ == '__main__':
    import sys

    if len(sys.argv) <> 3:
        print "Usage: %s  " % sys.argv[0]
        sys.exit(1)

    f = open(sys.argv[1])
    inputcss = f.read()
    f.close()
    open(sys.argv[2], 'w').write(minimalize(inputcss))

Agora é só configurar a COMPRESS_CSS_FILTERS para:

COMPRESS_CSS_FILTERS = ['seu.projeto.cssmin.CssMinFilter']

Para maiores informações sobre o django-compress acesse: http://code.google.com/p/django-compress/

Bom, chegamos ao fim dessa parte do artigo, em breve a última parte com mais aplicações que facilitam a sua vida na criação de um CMS com o django.

Até a próxima.

CMS com django Parte 1

Olá pessoas, nesse mês de janeiro comecei a desenvolver um CMS utilizando o ótimo framework Django. Durante o processo abracei a causa DRY (don’t repeat yourself) e acabei encontrado ótimas aplicações disponibilizadas pela comunidade. Nos próximos posts vou mostrar algumas aplicações que diminuem ainda mais o tempo necessário para construir uma aplicação de grande porte.

django-tagging

O django-tagging é uma aplicação de tags genérica, com ela possível criar tags específicas para cada tipo de objeto. Sendo assim, pode-se adicionar tags a qualquer modelo do seu projeto.

Digamos que tenha o seguinte modelo:

from django.db import models
class BlogPost(models.Model):
    title = models.CharField(max_length=30)
    body = models.TextField()
    date_posted = models.DateField()

É um simples modelo de post, mas para adicionar a funcionalidade de tags fazemos:

from django.db import models
from tagging.fields import TagField

class BlogPost(models.Model):
    title = models.CharField(max_length=30)
    body = models.TextField()
    date_posted = models.DateField()
    tags = TagField()

O django-tagging adiciona um novo campo chamado TagField onde as tags serão cadastradas. Para facilitar ainda mais pode adicionar os seguintes métodos:

def _get_tags(self):
    return Tag.objects.get_for_object(self)
def _set_tags(self, tag_list):
    Tag.objects.update_tags(self, tag_list)
tags = property(_get_tags, _set_tags)

Agora para obter as tags relacionadas ao BlogPost fazemos assim:

e = BlogPost.objects.get(pk=12)
e.tags # retorna a lista de tags
e.tags = 'foo bar' # agora o BlogPost possui as tags foo e bar

Então, imagine uma situação em que vários modelos da sua aplicação possuem um campo de tag, seria interessante descobrir quais são as tags usadas num determinado tipo de modelo, para isso podemos fazer:

from myapp.models import MyModel
from tagging.models import Tag
m1 = MyModel.objects.get(pk=1)
Tag.objects.update_tags(m1, 'house thing')
m2 = MyModel.objects.get(pk=2)
Tag.objects.update_tags(m2, 'cheese toast house')
Tag.objects.usage_for_model(MyModel)
[<Tag: cheese>, <Tag: house>, <Tag: thing>, <Tag: toast>]

O código retorna uma lista com todas as tags utilizadas pelo modelo MyModel. Ainda é possível saber quantas vezes cada tag foi usada pelo modelo.

tags = Tag.objects.usage_for_model(MyModel, counts=True)
[(tag.name, tag.count) for tag in tags]
[('cheese', 1), ('house', 2), ('thing', 1), ('toast', 1)]

Para ter o total de tags e limitar o mínimo para um determinado número usamos o argumento min_count.

tags = Tag.objects.usage_for_model(MyModel, min_count=2)
[(tag.name, tag.count) for tag in tags]
[('house', 2)]

Ainda é possível selecionar objetos baseados nas suas tags.

from tagging.models import TaggedItem
house_tag = Tag.objects.get(name='house')
TaggedItem.objects.get_by_model(MyModel, house_tag)
[<Widget: pk=1>, <Widget: pk=2>]

O django-tagging é muito poderoso para mais detalhes leia a documentação disponível no arquivo de download.
No próximo post estarei mostrando mais sobre o django-tinymce e do django-compress. Até a próxima!

Assault Cube

Bom, primeiro post de 2009, pra relaxar vai uma dica de jogo para o mundo Linux.

Trata-se do Assault Cube, um jogo FPS open source baseado na engine Cube, muito parecido com os counter-strike da vida. E melhor é somente 40mb!!!!

Ele suporta tanto modos single player, contra bots (já inclusos no game), e também o modo multiplayer (local e Internet). E talvez sua melhor característica seja a possibilidade de criar stages através do próprio jogo, basta apertar a tecla ‘e’ e começar a editar!

Existem versões para linux, windows e mac. Para baixa o jogo acesse http://assault.cubers.net

Abaixo algumas imagens do jogo.

Assault Cube

Assault Cube 01

Assault Cube 02

Assault Cube 02

Assault Cube 03

Assault Cube 03

Softwell Maker

Para quem não conhece, o Maker é uma ferramenta para criação de sistemas web de forma visual. O desenvolvedor não precisa ter conhecimentos avançados de programação para utilizá-lo, porque tudo é feito visualmente com a ajudas de assistentes e gráficos.

Durante essa semana participei de um treinamento dessa ferramenta, e analizando pessoalmente pude ver a capacidade desse sistema de desenvolvido pela empresa baiana Softwell. Abaixo seguem as minhas considerações sobre o Maker.

Como funciona?

O Maker foi desenvolvido em Delphi e (segundo seus representantes) não é um gerador de código fonte, mas se for necessário o mesmo também pode ser gerado.

Os sistemas desenvolvidos no Maker rodam, por padrão, num servidor de aplicações Java, como o Tomcat, por exemplo. Pode-ser gerar um arquivo .war e fazer o deploy num servidor que desejar.

As aplicações depedem do WEBRUN, que vem junto do Maker, e funciona como uma camada entre a aplicação desenvolvida e o servidor de aplicações.¬† Caso já possua um WEBRUN no servidor, também é possível exportar o sistema para um arquivo .jar e o incorporar a ela.

O Maker possui basicamente 3 funções para geração de sistemas, formulários, fluxos e relatórios.

Formulários

Atravéz de formulários acontecem as principais interações com o sistema. O Maker pode gerar automaticamente os formulários baseando-se nas tabelas e relacionamentos do banco de dados. Além de poder criar formulários, sem associação com fonte de dados e que execute uma tarefa em particular.

Fluxos

No Maker os fluxos substituem a codificação na hora de criar regras de negocio para a apliação. Tratam-se de fluxogramas que são associados a determinadas ações do sistema para realizar tomadas de decisão. Pode-se efetuar condições, loops, mensagens de error e retorno, além de um conjunto de funções já disponíveis como concatenação, obtenção de campos de tabelas, conversão de tipos primitivos, etc.

Relatórios

O Maker possui o Report Builder embutido, e o mesmo é utilizado para desenhar os relatórios necessários para a aplicação.

Na minha opinião!

Realmente, depois de presenciar o treinamento, posso dizer a utilização do Maker acelera sim o processo de criação de aplicações, principalmente no caso dos formulários, que podem ser gerados automaticamente a partir de uma fonte de dados.

Porém, é necessário tempo para se tornar um “expert” na utilização do Maker, o mesmo tempo que se levaria para aprender a utilizar um framework como Django, Ruby on Rails ou Grails, por exemplo. E o que, na minha opinião, seria a grande vantagem de uma ferramenta visual sobre os outros, a curva de aprendizagem, é parecida com a desses frameworks.

Eu devo concordar com esse post do guj, em que o usuário kicolobo diz:

Programação OO é ignorada. O código é gerado em Java e C#, porém o processo de desenvolvimento do Maker é procedural. Todos os diagramas são procedurais. Em momento algum (pelo menos na demonstração que vimos), foi criada uma classe de entidade (ou mesmo uma entidade qualquer). Tudo é relacionado diretamente com o banco de dados. Para quem já trabalha com OO, o Maker pode ser visto como retrocesso.

E realmente é verdade, hoje em dia fala-se muito mais em OO e MVC, voltar o desenvolvimento para as tabelas do banco de dados é praticamente um retrocesso. No django, por exemplo, só é necessário configurar o banco de dados, o desenvolvedor não precisa criar as tabelas, o django executa todo esse processo e também cria os formulários automaticamente.

Uma coisa que me incomodou bastante foi a quantidade de cliques necessários para fazer uma concatenação de texto com algumas variáveis. Algo que em python, por exemplo, poderia ficar assim:

texto = "O total da conta do cliente %s foi de %f reais" % (nome,total)

Outro fato importante é que por ser um sistema proprietário, a comunidade do maker praticamente não existe, se comparada com de outras tecnologias, sendo assim, sempre que precisarmos de ajuda temos que recorer ao suporte a softwell.

Conclusão

Analisando o esquema geral, eu não compraria uma licença do Maker para uso pessoal. Além dos fatos mencionados acima, um ambiente de Software Livre me agrada mais, sabendo que a existe uma comunidade por trás ajudando a manter e melhorar o sistema, diferente do modelo proprietário, onde estamos a mercê da empresa dona do sistema.

Utilizando iw.fss no Plone 2.5

Uma das grandes vantagens do Zope/Plone é o seu banco de dados ZODB, porém existem situações onde é necessário armazenar grandes quantidades de arquivos, ou arquivos muito grandes. Isso pode acarretar no crescimento desnecessário do Data.fs. Uma das soluções existentes é a utilização do produto FileSystemStorage. O que ele faz é, disponibilizar um novo tipo storage para Archetypes, onde os valores dos campos como arquivos e imagens são armazenados no sistema de arquivos.

Primeiro precisamos baixar uma versão compatível com o Plone 2.5, segundo a página do produto a versão mais atual (2.7.1) só é suportada pela versão 3 do Plone. Sendo assim vamos precisar da versão 2.7.0, disponível aqui.

Instalação:

Existem 3 maneiras de instalar o FSS.

1ª) EGG

Baixe este egg, e utilize o easy_install para instalar.

# easy_install iw.fss-2.7.0-py2.4.egg

2ª)Instalando do SVN

Não encontrei o tar.gz da versão 2.7.0, sendo assim, baixei do repositório.

# svn export http://svn.plone.org/svn/collective/iw.fss/tags/2.7.0/ iw.fss
# cd iw.fss
# python setup.py install

3ª) Copiando para lib/pyton

Segue os mesmos passos acima, porém, ao invés de excutar o último comando, copiamos a pasta iw para a lib/python da sua instância.

# svn export http://svn.plone.org/svn/collective/iw.fss/tags/2.7.0/ iw.fss
# cd iw.fss
# cp iw $INSTANCE_HOME/lib/python

Configuração

Podemos notar que o FSS já adota os padrões do zope 3, ou seja, não é simplesmente extrair seu conteúdo na pasta Products e pronto. Para que ele seja carregado necessitamos criar algums arquivos zcml.

$INSTANCE_HOME/etc/package-includes/iw.fss-meta.zcml, com a linha:

<include package="iw.fss" file="meta.zcml"/>

$INSTANCE_HOME/etc/package-includes/iw.fss-configure.zcml, com a linha:

<include package="iw.fss" />

OBS.: No Plone 2.5 pode acontecer de não existir a pasta package-include em $INSTANCE_HOME/etc, se for este o caso será necessário copiar o conteúdo de $ZOPE_HOME/lib/python/Products/Five/skel para $INSTANCE_HOME/etc.

Agora abra o arquivo $INSTANCE_HOME/lib/python/iw/fss/etc/plone-filesystemstorage.conf e defina as variáveis abaixo:

storage-path $$INSTANCE_HOME/var/fss_files
backup-path $$INSTANCE_HOME/var/fss_backup
storage-strategy flat

storage-path e backup-path são, respectivamente, os caminhos de onde ficarão os arquivos e os backups. Já storage-strategy é tipo de estratégia utilizada para armezar os arquivos, por enquanto vamos deixar a estratégia padrão ‘flat’.

Verifique se o FSS está diponível para instalação. Caso sim, você fez tudo corretamente. Seguindo…

Alterando o storage para arquivos e imagens

Até agora o que fizemos foi instalar e configurar o FSS, mas só isso não basta. Para que os arquivos e as imagens dos content-types padrão do Plone (News Item, File e Image) passem a utilizá-lo precisamos de mais um passo. Adcione a seguinte linha em algum dos arquivos em $INSTANCE_HOME/etc/package-includes:

<include package="iw.fss" file="atct.zcml" />

Agora reinicie o zope e adicione uma nova imagem ou arquivo e verifique na pasta que você definiu como storage e note que agora existe um arquivo lá.

Definindo tipos em produtos personalizados

Muitas vezes somente os tipos padrão do plone não suficientes, e temos que criar nossos próprios tipos. Para utilizar o FSS em nossos produtos personalizados fazemos o seguinte:


from iw.fss.FileSystemStorage import FileSystemStorage
...
my_schema = Schema((
    FileField('file',
              ...
              storage=FileSystemStorage(),
              widget=FileWidget(...)
              ),
    ...
    ))
 ...

Bem simples, faça o mesmo na definição do seu tipo e o arquivo será salvo no sistema de arquivos. Para quem usa o Plone 3, os passos são parecidos, porém pode-se utilizar o buildout para facilitar ainda mais o processo.

Esse foi o meu primeiro(de muitos) tutorial, espero que gostem. t+