Accesso autenticato a Plone via urllib2
Usando l’idea presa da http://www.matejdrame.com/blog/python-post-get-requests-cookies/ (grazie Matej :)), con questo pezzetto di codice è facile autenticarsi ad un sito Plone (il mio era un 2.1) e continuare a fare richieste da autenticato:
from urllib import urlencode
from cookielib import CookieJar
import urllib2
portal_url = 'http://127.0.0.1:8080/plone'
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(CookieJar()))
opener.open(portal_url+'/login_form',
data=urlencode({'__ac_name': 'admin', '__ac_password': 'admin'}))
basta a questo punto aprire le nostre url con l’opener così inizializzato:
resp = opener.open(portal_url + 'riservato')
Products.pipbox in Plone
Da un bel po’ volevo scrivere io a riguardo, ma qui mi hanno anticipato, e molto bene! :)
http://www.coresoftwaregroup.com/blog/simple-way-to-add-lightbox-thickbox-support-to-plone-3-site
In sostanza con pipbox installare e usare JQuery Tools in Plone è un lampo!
come dice Chris:
- scarica e installa pipbox
- vai al portal_properties e modifica il property sheet di pipbox aggiungendo le regole che dinamizzano le tue pagine
es. una regola come la seguente permette di aprire in un overlay le vostre immagini:
{type:'overlay',subtype:'image',selector:'img.image-right,img.image-left,img.image-inline', urlmatch:'/image_.+$',urlreplace:''}
Grazie a Steve McMahon, autore di pipbox!!
BFG ha il suo libro!
Ed è completamente Open, come il codice.
BFG (http://bfg.repoze.org) è un interessante web framework scritto in Python, che da molti mesi sta guadagnando attenzione e massa critica.
Una delle sue caratteristiche dichiarate è quella di essere completamente documentato, e questo ha portato a scrivere il primo libro su BFG, perfettamente allineato all’ultima versione rilasciata:
http://plope.com/static/bfg-1.2b1dev.pdf
Chris McDonough, che è l’autore principale del software, è anche l’autore principale del libro, e, come sottolinea Paul Everitt nella prefazione, questo è qualcosa di piuttosto inedito.
Wyn Williams - Drupal Experiences, or why they need to try harder
Per organizzazioni di un certo livello Drupal zoppica nei fondamentali limitando ciò che è permesso fare e aumentando i costi di sviluppo per ottenere in cambio molto poco da quel che vedo, un progetto che potrebbe durare sei mesi con Drupal richiederebbe poche settimane con Plone.
Drupal is far more capable than a CMS like WordPress, but also much less flexible than a pure framework.
But more importantly, the facts that Drupal isn’t object-oriented, isn’t MVC/MTV, doesn’t have an ORM, and is generally less flexible than a pure framework, not to mention our preference for working in Python over PHP, all contribute to our decision not to use it.
Scot Hacker - Drupal or Django? A Guide for Decision Makers
Drupal è un qualcosa a metà tra un framework e un CMS che abbiamo scelto di non adottare.
Drupal è molto più capace di un CMS come WordPress, ma anche molto meno flessibile di un framework puro.
Cosa più importante, il fatto che Drupal non è orientato agli oggetti, non è MVC/MTV, non ha un ORM, e in generale è meno flessibile di un framework puro, per non citare la nostra preferenza di lavorare in Python piuttosto che PHP, tutto questo ha contribuito alla nostra decisione di non adottarlo.
ContentMirror modificato per esportare traduzioni LinguaPlone
Le traduzioni di LinguaPlone non sono attualmente gestite da ContentMirror (è ancora nella Maybe list..). Aimè, ne ho bisogno urgentemente e decido di patchare il prodotto..
Ecco come:
1. Nel modulo schema.py va aggiunta la struttura per la tabella translations:
translations = rdb.Table(
"translations",
metadata,
rdb.Column( "source_id", rdb.Integer,
rdb.ForeignKey('content.content_id', ondelete='CASCADE'),
primary_key=True ),
rdb.Column( "target_id", rdb.Integer,
rdb.ForeignKey('content.content_id', ondelete='CASCADE'),
primary_key=True),
rdb.Column( "target_language", rdb.String(8), primary_key=True ),
rdb.Column( "target_state", rdb.String(64), primary_key=False )
)
class Translation( object ):
def __init__( self, source=None, target=None, target_language=None, target_state=None):
self.source = source
self.target = target
self.target_language = target_language
self.target_state = target_state
orm.mapper( Translation, translations,
properties = {
'source': orm.relation(Content, uselist=False, backref='translations',
primaryjoin=content.c.content_id==translations.c.source_id ),
'target': orm.relation(Content, uselist=False,
primaryjoin=content.c.content_id==translations.c.target_id ),
})
NB: ricordate di rilanciare il comando DDL per ottenere la struttura della tabella da creare nel DB..
2. Nel modulo transform.py va aggiunta la gestione delle info delle traduzioni (che non sono agganciate a campi Archetypes, per questo non si riesce a lavorare in modo più *pulito*..). Ho fatto questo modificando il metodo copy della classe SchemaTransformer come segue:
def copy( self, instance, peer ):
for field in self.context.Schema().fields():
transformer = component.queryMultiAdapter( ( field, self ))
transformer.copy( instance, peer )
# gestione LinguaPlone
value = instance.getTranslations( )
if not value:
return
for lang, (ob, review_state) in value.items():
# no language specified
if not lang:
continue
# not recording the context itself
if ob.UID() == instance.UID():
continue
t_oid = ob.UID()
# fetch the remote side's peer
peer_ob = schema.fromUID( ob.UID() )
if peer_ob is None:
serializer = interfaces.ISerializer( ob, None )
if serializer is None: continue
peer_ob = serializer.add()
# create the translation
translation = schema.Translation( peer, peer_ob, lang, review_state)
Lanciate il bulk e vedrete comparire le info delle vostre traduzioni nella tabella appena creata :)
SQLAlchemy ProgrammingError: Can’t adapt INSERT…
Se ricevi tale errore NON cercare lontano.. ricontrolla tutti i campi che valorizzi uno per uno e verifica che tutti siano del tipo giusto!!
Controlla che nei campi booleani non finiscano stringhe e così via!
Niente di esotico, o di particolare.. ma abbastanza per fare le 2 di notte pensando che sia un problema di SQLAlchemy :/
Que Viva ZODB !!
Assegnare ruoli locali agli oggetti Plone in modo personalizzato
borg.localrole fa molto bene il suo lavoro!
piazzalo nel buildout, importalo nel configure.zcml del tuo pacchetto, definisci il tuo adapter e il gioco è fatto!
Nota: lancia lo step di importazione fornito col pacchetto in portal_setup!
un paio di adapter a cui ispirarsi sono quelli forniti dal pacchetto stesso: quello di default (che permette alla policy di base di funzionare con il plugin attivato) e quello fornito per lavorare come necessario sugli oggetti temporanei generati dal portal_factory..
piazzare un’icona nelle action della personal bar in Plone 3.2
mi trovo a scriverlo dato che non era affatto chiaro il modo più rapido :/
alla fine dovrebbe bastare:
- piazzare nella action, nella proprietà “icon” un’espressione che risulti True (es. python:True)
- piazzare nel CSS una classe corrispondente a .actionicon-categoria_azione-id_azione in cui definire il proprio background image a piacere
