Turbogears - Guida rapida

Cos'è Web Framework?

Web Application Framework o semplicemente Web Framework rappresenta una raccolta di librerie e moduli, che consente a uno sviluppatore di applicazioni Web di scrivere applicazioni, senza doversi preoccupare di dettagli di basso livello come protocolli, gestione dei thread, ecc.

Cos'è TurboGears?

TurboGears è un framework per applicazioni web scritto in Python. Creata originariamente da Kevin Dangoor nel 2005, la sua ultima versione TurboGears (ver 2.3.7) è gestita da un gruppo di sviluppatori guidati da Mark Ramm e Florent Aide.

TurboGears segue il paradigma Model-View-Controller così come la maggior parte dei framework web moderni come Rails, Django, Struts, ecc.

Model View Controller

MVC è un modello di progettazione software per lo sviluppo di applicazioni web. Un pattern Model View Controller è composto da tre parti:

  • Model - Il livello più basso del pattern è responsabile del mantenimento dei dati.

  • View - Questo è responsabile della visualizzazione di tutti o una parte dei dati all'utente.

  • Controller - Codice software che controlla le interazioni tra il Modello e la Vista.

MVC è popolare in quanto isola la logica dell'applicazione dal livello dell'interfaccia utente e supporta la separazione dei problemi. Qui, il Titolare riceve tutte le richieste dell'applicazione e poi lavora con il Modello per preparare i dati necessari alla View. The View utilizza quindi i dati preparati dal Titolare per generare una risposta presentabile finale. L'astrazione MVC può essere rappresentata graficamente come segue:

Il modello

Il Modello è responsabile della gestione dei dati dell'applicazione. Risponde alla richiesta della vista e risponde anche alle istruzioni del controller per aggiornarsi.

La vista

Una presentazione dei dati in un formato particolare, innescata dalla decisione di un responsabile del trattamento di presentare i dati. Sono sistemi di creazione di modelli basati su script molto facili da integrare con la tecnologia AJAX.

Il controller

Il controller è responsabile della risposta all'input dell'utente ed esegue le interazioni sugli oggetti del modello di dati. Il Controller riceve l'input, convalida l'input e quindi esegue l'operazione di business che modifica lo stato del modello dati.

TurboGears si basa su una serie di librerie e strumenti. Questi strumenti sono cambiati tra le diverse versioni di TurboGears. I componenti della versione corrente (ver 2.3.7) sono elencati di seguito.

SQLAlchemy

È un kit SQL open source che fornisce ORM (Object Relation Mapping) per il codice Python.

Genshi

Questo motore di template viene utilizzato per costruire il front-end delle applicazioni TG. Un sistema di modelli Web combina un modello con una determinata origine dati per eseguire il rendering di pagine Web dinamiche.

ToscaWidgets

È una libreria di widget per la generazione di moduli HTML con controlli lato server. Tosca funge anche da middleware per connettersi con widget e toolkit JavaScript.

Riduttore

Fornisce una serie di comandi per gestire i progetti e le applicazioni TurboGears del server. Le applicazioni TurboGears possono essere distribuite su qualsiasi server Web conforme a WSGI.

La Web Server Gateway Interface (WSGI) è stata adottata come standard per lo sviluppo di applicazioni web Python. WSGI è una specifica per l'interfaccia universale tra server web e applicazioni web. Il pacchetto wsgiref è un'implementazione di riferimento di WSGI. Viene utilizzato per aggiungere il supporto WSGI al framework web TurboGears web. Il modulo simple_server in questo pacchetto implementa un semplice server HTTP che serve le applicazioni WSGI. Lo useremo per testare le applicazioni sviluppate durante questo tutorial.

Prerequisito

Python 2.6 o versioni successive. Le versioni precedenti di TurboGears non erano compatibili con Python 3.X. L'ultima versione afferma di funzionare bene su Python 3.X. Tuttavia, la documentazione ufficiale di TurboGears è ancora basata sull'ambiente Python 2.7.

Il seguente comando installs virtualenv -

pip install virtualenv

Questo comando ha bisogno di administratorprivilegi. Inseriscisudo before pipsu Linux / Mac OS. Se sei su Windows, accedi come amministratore. Su Ubuntu virtualenv può essere installato utilizzando il suo gestore di pacchetti.

Sudo apt-get install virtualenv

Una volta installato, il nuovo ambiente virtuale viene creato in una cartella.

mkdir newproj
cd newproj
virtualenv venv

Per attivare l'ambiente corrispondente, attiva Linux/OS X

venv/bin/activate

sopra Windows

venv\scripts\activate

Ora siamo pronti per install TurboGearsin questo ambiente. Un'installazione minima di TurboGears viene eseguita seguendo il comando:

pip install TurboGears2

Il comando precedente può essere eseguito direttamente senza ambiente virtuale per l'installazione a livello di sistema.

Per installare TurboGears insieme agli strumenti di sviluppo, utilizzare il seguente comando:

pip install tg.devtools

TurboGears ha una modalità minima che consente di creare rapidamente applicazioni a file singolo. È possibile creare rapidamente esempi e servizi semplici con un insieme minimo di dipendenze.

La classe dell'applicazione in un'applicazione TG viene ereditata da TGControllerclasse. I metodi in questa classe sono disponibili per l'accesso da parte di@expose decoratore da tgmodulo. Nella nostra prima applicazione,index()metodo è mappato come root della nostra applicazione. Anche la classe TGController deve essere importata datg modulo.

from tg import expose, TGController
class MyController(TGController):
   @expose()
   def index(self):
      return 'Hello World turbogears'

Quindi, impostare la configurazione dell'applicazione e dichiarare l'oggetto dell'applicazione. AppConfig il costruttore della classe qui accetta due parametri: l'attributo minimo impostato su true e la classe del controller.

config = AppConfig(minimal = True, root_controller = RootController())
application = config.make_wsgi_app()

Il make_wsgi_app() la funzione qui costruisce l'oggetto dell'applicazione.

Per poter servire questa applicazione, ora dobbiamo avviare il server HTTP. Come accennato in precedenza, useremosimple_server modulo in wsgirefpacchetto per configurarlo e avviarlo. Questo modulo hamake_server() metodo che richiede il numero di porta e l'oggetto dell'applicazione come argomenti.

from wsgiref.simple_server import make_server
server = make_server('', 8080, application)
server.serve_forever()

Significa che la nostra applicazione verrà servita al numero di porta 8080 di localhost.

Quello che segue è il codice completo della nostra prima applicazione TurboGears -

app.py

from wsgiref.simple_server import make_server
from tg import expose, TGController, AppConfig

class MyController(TGController):

   @expose()
   def index(self):
      return 'Hello World TurboGears'
		 
config = AppConfig(minimal = True, root_controller = MyController())
application = config.make_wsgi_app()

print "Serving on port 8080..."
server = make_server('', 8080, application)
server.serve_forever()

Esegui lo script sopra dalla shell Python.

Python app.py

accedere http://localhost:8080 nella barra degli indirizzi del browser per visualizzare il messaggio "Hello World TurboGears".

Il tg.devtoolsdi TurboGears contiene Gearbox. È un insieme di comandi, utili per la gestione di progetti TG più complessi. I progetti full stack possono essere creati rapidamente con il seguente comando Gearbox:

gearbox quickstart HelloWorld

Questo creerà un progetto chiamato HelloWorld.

Un progetto TurboGears contiene le seguenti directory:

  • Config - Dove si basa l'impostazione e la configurazione del progetto

  • Controllers - Tutti i controllori di progetto, la logica dell'applicazione web

  • i018n - File di traduzione per le lingue supportate

  • Lib - Funzioni e classi di utilità python

  • Model - Modelli di database

  • Public Static Files - CSS, JavaScript e immagini

  • Templates - Modelli esposti dai nostri controllori.

  • Tests - La serie di test effettuati.

  • Websetup - Funzioni da eseguire durante la configurazione dell'applicazione.

Come installare un progetto

Questo progetto ora deve essere installato. UNsetup.pyè già fornito nella directory di base del progetto. Le dipendenze del progetto vengono installate quando viene eseguito questo script.

Python setup.py develop

Per impostazione predefinita, le seguenti dipendenze vengono installate al momento della configurazione del progetto:

  • Beaker
  • Genshi
  • zope.sqlalchemy
  • sqlalchemy
  • alembic
  • repoze.who
  • tw2.forms
  • tgext.admin ≥ 0.6.1
  • WebHelpers2
  • babel

Dopo l'installazione, inizia a servire il progetto sul server di sviluppo immettendo il seguente comando nella shell:

Gearbox serve –reload –debug

Segui il comando sopra menzionato per servire un progetto di esempio predefinito. Apertohttp://localhost:8080nel browser. Questa applicazione di esempio già pronta fornisce una breve introduzione sul framework stesso di TurboGears.

In questo progetto Hello, il controller predefinito viene creato nella directory dei controller come Hello/hello/controllers.root.py. Lasciatecimodify root.py con il seguente codice -

from hello.lib.base import BaseController
from tg import expose, flash

class RootController(BaseController):
   movie = MovieController()
   @expose()
   def index(self):
      return "<h1>Hello World</h1>"
		
   @expose()
   def _default(self, *args, **kw):
      return "This page is not ready"

Una volta che un'applicazione di lavoro di base è pronta, è possibile aggiungere più visualizzazioni nella classe controller. NelMycontroller classe sopra, un nuovo metodo sayHello()è aggiunto. Il@expose() decoratore attribuisce /sayHelloURL ad esso. Questa funzione è progettata per accettare un nome come parametro dall'URL.

Dopo aver avviato il server tramite il comando "gearbox serve", http://localhost:8080. Il messaggio Hello World verrà visualizzato nel browser, anche se vengono inseriti i seguenti URL:

http://localhost:8080/

http://localhost:8080/index

Tutti questi URL sono associati a RootController.index()metodo. Anche questa classe ha_default()metodo che verrà richiamato, ogni volta che un URL non è mappato a nessuna funzione specifica. La risposta all'URL è mappata a una funzione dal decoratore @expose ().

È possibile inviare un parametro a una funzione esposta dall'URL. La seguente funzione legge il parametro name dall'URL.

@expose()
def sayHello(self, name):
   return '<h3>Hello %s</h3>' %name

Il seguente output verrà visualizzato nel browser come risposta all'URL: http://localhost:8080/?name=MVL

Hello MVL

TurboGears mappa automaticamente i parametri URL sugli argomenti della funzione. La nostra classe RootController viene ereditata da BaseController. Questo è definito comebase.py nel lib folder di applicazione.

Il suo codice è il seguente:

from tg import TGController, tmpl_context
from tg import request

__all__ = ['BaseController']

def __call__(self, environ, context):
   tmpl_context.identity = request.identity
   return TGController.__call__(self, environ, context)

TGController.__call__ invia al metodo Controller a cui viene indirizzata la richiesta.

Un evento sebbene il contenuto HTML possa essere restituito al browser, per un output più avanzato, è sempre preferibile l'uso del motore di modelli. In un progetto full stack "avviato rapidamente" da gearbox, Genshi è abilitato come renderer di modelli predefinito. In un'applicazione minima, tuttavia, Genshi (o qualsiasi altro motore di modelli, come jinja) deve essere installato e abilitato. Il motore di modelli Genshi consente di scrivere modelli in puro xhtml e li convalida per rilevare problemi in fase di compilazione e prevenire la pubblicazione di pagine interrotte.

I modelli vengono indicati utilizzando una notazione puntata. Nel nostro progetto Hello viene fornita una directory dei modelli per memorizzare le pagine web dei modelli. Quindisample.html sarà indicato come hello.templates.sample(estensione non menzionata). TurboGears esegue il rendering di questo modello tramite un decoratore di esposizione per collegare il metodo del controller ad esso tramitetg.render_template() funzione.

La funzione controller esposta restituisce un oggetto dizionario Python. Questo oggetto dizionario viene a sua volta passato al modello collegato. I segnaposto nel modello vengono riempiti con i valori del dizionario.

Per cominciare, mostriamo una pagina web con un semplice script html. Il controller esposto restituisce un filenull dictionary object poiché non intendiamo inviare alcun dato da analizzare all'interno dello script HTML.

Come creare un codice HTML di esempio

Nostro sample.htmlè dato di seguito. Assicurati che sia archiviato nella directory dei modelli del progetto.

<html>
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <h2>Hello, Welcome to TurboGears!.</h2>
   </body>
</html>

Inserisci sample() funzione in root.py ed esponi sample.html attraverso di esso.

@expose("hello.templates.sample")
   def sample(self):
      return {}

Il seguente risultato verrà visualizzato nel browser quando un URL http://localhost:8080/sample viene inserito dopo aver avviato il server web.

Come accennato in precedenza, un oggetto dizionario viene inviato come raccolta di parametri a un modello Genshi. Questo modello contiene "segnaposto", che vengono riempiti dinamicamente con i parametri ricevuti dal controller.

Cambiamo il file sample() funzione per inviare un oggetto dizionario al modello di esempio.

@expose("hello.templates.sample")
   def sample(self,name):
      mydata = {'person':name}
      return mydata

Creare sample.html nella cartella dei modelli (templates\sample.html)

<html>
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <h2>Hello, my name is ${person}!.</h2>
   </body>
</html>

Nel codice HTML sopra, ${person}è il segnaposto. accederehttp://localhost:8080/sample?name=MVLcome URL nel browser. Questo URL è associato asample()metodo nel nostro controller di root. Restituisce un oggetto dizionario. Viene selezionato dalla pagina del modello collegata sample.html nella directory dei modelli. La $ {person} viene quindi sostituita da MVL nella pagina web.

È anche possibile accedere ai dati del modulo HTML in una funzione del controller. Il modulo HTML utilizza per inviare i dati del modulo.

Il protocollo HTTP è il fondamento della comunicazione dati nel world wide web. In questo protocollo sono definiti diversi metodi di recupero dei dati dall'URL specificato. La seguente tabella riassume i diversi metodi http:

Sr.No. Metodi e descrizione HTTP
1

GET

Invia i dati in forma non crittografata al server. Metodo più comune.

2

HEAD

Uguale a GET, ma senza corpo di risposta

3

POST

Utilizzato per inviare i dati del modulo HTML al server. I dati ricevuti dal metodo POST non vengono memorizzati nella cache dal server.

4

PUT

Sostituisce tutte le rappresentazioni correnti della risorsa di destinazione con il contenuto caricato.

5

DELETE

Rimuove tutte le rappresentazioni correnti della risorsa di destinazione fornita da un URL

Creazione di un modulo HTML

Creiamo un modulo HTML e inviamo i dati del modulo a un URL. Salva il seguente script come login.html

<html>
   <body>
      <form action = "http://localhost:8080/login" method = "get">
         <p>Enter Name:</p>
         <p><input type = "text" name = "nm" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
   </body>
</html>

I dati inseriti in questo modulo devono essere inviati a ‘/login’ URL. Ora crea una funzione controllerloginpage() ed esporre ad esso la pagina html sopra.

@expose("hello.templates.login")
   def loginpage(self):
      return {}

Per ricevere i dati del modulo, fornire un login()controller, che ha attributi del modulo come parametri. Qui‘nm’ è il nome del campo di immissione del testo nel modulo di login, lo stesso viene utilizzato come parametro della funzione login ().

@expose("hello.templates.sample")
   def login(self, nm):
      name = nm
      return {'person':name}

Come si può vedere, i dati ricevuti dal form di login vengono inviati al template sample.html (usato in precedenza). Viene analizzato da aGenshi template engine per generare il seguente output -

Metodo POST

Quando il modulo HTML utilizza il metodo POST per inviare i dati all'URL nell'attributo di azione, i dati del modulo non vengono esposti nell'URL. I dati codificati vengono ricevuti in un filedictargomento dalla funzione controller. Il **kw l'argomento seguente è l'oggetto dizionario che contiene i dati.

Il modulo HTML contiene due campi di testo di input.

<html>
   <body>
	
      <form action = "http://localhost:8080/marks" method = "post">
         <p>Marks in Physics:</p>
         <p><input type = "text" name = "phy" /></p>
         <p>Marks in Maths:</p>
         <p><input type = "text" name = "maths" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
		
   </body>	
</html>

Il marks() controller riceve i dati del modulo e li invia a sample.htmlmodello. Codice perroot.py è il seguente -

from hello.lib.base import BaseController
from tg import expose, request

class RootController(BaseController):
   @expose("hello.templates.marks")
   def marksform(self):
      return {}
		
   @expose("hello.templates.sample")
   def marks(self, **kw):
      phy = kw['phy']
      maths = kw['maths']
      ttl = int(phy)+int(maths)
      mydata = {'phy':phy, 'maths':maths, 'total':ttl}
      return mydata

Infine, il modello sample.html è il seguente:

<html>
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <h2>Hello, Welcome to TurboGears!.</h2>
      <h3>Marks in Physics: ${phy}.</h3>
      <h3>Marks in Maths: ${maths}.</h3> <h3>Total Marks: ${total}</h3>
   </body>
	
</html>

Avvia il server (se non è già in esecuzione)

Gearbox server –reload –debug

accedere http://localhost::8080/marksform nel browser

Il sample.html renderà il seguente output -

Genshi è un linguaggio per modelli basato su XML. È simile aKid, che era il motore dei modelli per le versioni precedenti di TurboGears. Genshi e Kid si ispirano ad altri linguaggi di template ben noti comeHSLT, TAL e PHP.

Un modello Genshi è costituito da direttive di elaborazione. Queste direttive sono elementi e attributi in un modello. Le direttive Genshi sono definite in uno spazio dei nomihttp://genshi.edgewall.org/. Quindi questo spazio dei nomi deve essere dichiarato nell'elemento radice del modello.

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
...
</html>

La dichiarazione sopra indica che lo spazio dei nomi predefinito è impostato su XHTML e le direttive Genshi hanno il prefisso "py".

Direttive Genshi

Un certo numero di direttive sono definite in Genshi. Il seguente elenco elenca le direttive Genshi:

  • py:if
  • py:choose
  • py:for
  • py:def
  • py:match
  • py:with
  • py:replace
  • py:content
  • py:attrs
  • py:strip

Sezioni condizionali

Genshi fornisce due direttive per la riproduzione condizionale del contenuto: py: if e py: choose.

py: if

Il contenuto dell'elemento di questa direttiva verrà visualizzato solo se l'espressione in if clauserestituisce true. Supponendo che i dati nel contesto del modello siano{‘foo’:True, ‘bar’:’Hello’}, la seguente direttiva -

<div>
   <b py:if = "foo">${bar}</b>
</div>

risulterà in

Hello

Questo output, tuttavia, non verrebbe visualizzato se ‘foo’ is set to False.

Questa direttiva può essere utilizzata anche come elemento. In questo caso<py:if> deve essere chiuso da corrispondente </py:if>

<div>
   <py:if test = "foo">
      <b>${bar}</b>
   </py:if>
</div>

py: scegli

L'elaborazione condizionale avanzata è possibile con l'uso di py:choose in combinazione con py:when e py:otherwisedirettive. Questa funzione è simile aswitch – case costruire in C/C++.

Espressione in py:choose viene verificata la direttiva con valori diversi identificati con py:whenle alternative e i contenuti corrispondenti verranno resi. Un'alternativa predefinita può essere fornita sotto forma dipy:otherwise direttiva.

<div py:choose = "foo”>
   <span py:when = "0">0</span>
   <span py:when = "1">1</span>
   <span py:otherwise = "">2</span>
</div>

L'esempio seguente illustra l'uso di py:choose e py:whendirettive. Il modulo HTML invia i dati a / contrassegna l'URL. Ilmarks() funzione reindirizza i contrassegni e i risultati sotto forma di un oggetto dizionario a total.htmlmodello. La visualizzazione condizionale diresult Pass/Fail si ottiene utilizzando py:choose e py:when direttive.

Script HTML per l'inserimento di segni (marks.html) è il seguente:

<html>
   <body>
      <form action = "http://localhost:8080/marks" method = "post">
         <p>Marks in Physics:</p>
         <p><input type = "text" name = "phy" /></p>
         <p>Marks in Maths:</p>
         <p><input type = "text" name = "maths" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
   </body>
</html>

Il codice completo di root.pyè come segue. Ilmarks() il controller sta inviando contrassegni e risultati a total.html modello -

from hello.lib.base import BaseController
from tg import expose, request

class RootController(BaseController):
   @expose("hello.templates.marks")
      def marksform(self):
      return {}
		
   @expose("hello.templates.total")
      def marks(self, **kw):
      phy = kw['phy']
      maths = kw['maths']
      ttl = int(phy)+int(maths)
      avg = ttl/2
		
      if avg ≥ 50:
         mydata = {'phy':phy, 'maths':maths, 'total':ttl, 'result':2}
      else:
         mydata = {'phy':phy, 'maths':maths, 'total':ttl,'result':1}
	
      return mydata

Il total.html nella cartella dei modelli riceve i dati del dizionario e li analizza nell'output html in modo condizionale come segue:

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
	
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <h2>Hello, Welcome to TurboGears!.</h2>
      <h3>Marks in Physics: ${phy}.</h3> <h3>Marks in Maths: ${maths}.</h3>
      <h3>Total Marks: ${total}</h3>
		
      <div py:choose = "result">
         <span py:when = "1"><h2>Result: Fail</h2></span>
         <span py:when = "2"><h2>Result: Pass</h2></span>
      </div>
		
   </body>
</html>

Avvia il server (se non è già in esecuzione)

Gearbox server –reload –debug

accedere http://localhost::8080/marksform nel browser -

Il total.html renderà il seguente output -

py: per

Elemento in py: la direttiva for viene ripetuta per ogni elemento in un iterabile, tipicamente un oggetto List Python. Seitems = [1,2,3] è presente in un contesto di modello, può essere ripetuto seguendo py: per la direttiva -

<ul>
   <li py:for = "item in items">${item}</li>
</ul>

Verrà eseguito il rendering del seguente output:

1
2
3

L'esempio seguente mostra i dati del modulo HTML resi nel modello total.html utilizzando py: la direttiva può essere utilizzata anche come segue:

<py:for each = "item in items">
   <li>${item}</li>
</py:for>

Script modulo HTML

<html>
   <body>
	
      <form action = "http://localhost:8080/loop" method="post">
         <p>Marks in Physics:</p>
         <p><input type = "text" name = "phy" /></p>
         <p>Marks in Chemistry:</p>
         <p><input type = "text" name = "che" /></p>
         <p>Marks in Maths:</p>
         <p><input type = "text" name = "maths" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
		
   </body>
</html>

Il loop() il controller legge i dati del modulo e li invia a total.template sotto forma di un oggetto elenco.

from hello.lib.base import BaseController
from tg import expose, request

class RootController(BaseController):
   @expose("hello.templates.marks")
   def marksform(self):
   return {}
	
   @expose("hello.templates.temp")
   def loop(self, **kw):
      phy = kw['phy']
      maths = kw['maths']
      che = kw['che']
      l1 = []
      l1.append(phy)
      l1.append(che)
      l1.append(maths)
		
   return ({'subjects':['physics', 'Chemistry', 'Mathematics'], 'marks':l1})

Il modello temp.html utilizza il ciclo py: for per eseguire il rendering dei contenuti dell'oggetto dict sotto forma di tabella.

<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:py = "http://genshi.edgewall.org/" lang = "en">
	
   <body>
      <b>Marks Statement</b>
      <table border = '1'>
         <thead>
            <py:for each = "key in subjects"><th>${key}</th></py:for>
         </thead>
         <tr>
            <py:for each = "key in marks"><td>${key}</td></py:for>
         </tr>
      </table>
   </body>
</html>

Avvia il server (se non è già in esecuzione)

gearbox server –reload –debug

accedere http://localhost::8080/marksform nel browser.

Il seguente output verrà visualizzato nel browser quando viene inviato il modulo sopra.

py: def

Questa direttiva viene utilizzata per creare una macro. Una macro è uno snippet riutilizzabile di codice modello. Proprio come una funzione Python, ha un nome e può opzionalmente avere parametri. L'output di questa macro può essere inserito in qualsiasi punto di un modello.

La direttiva py: def segue la seguente sintassi:

<p py:def = "greeting(name)">
   Hello, ${name}!
</p>

Questa macro può essere rappresentata con un valore variabile al parametro "nome".

${greeting('world')} ${greeting('everybody)}

Questa direttiva può essere utilizzata anche con un'altra versione della sintassi come segue:

<py:def function = "greeting(name)">
   <p>Hello, ${name}! </p>
</py:def>

Nell'esempio seguente, macro() controller in root.py invia un dict oggetto con due chiavi nome1 e nome2 al modello macro.html.

from hello.lib.base import BaseController
from tg import expose, request

class RootController(BaseController):
   @expose('hello.templates.macro')
   def macro(self):
      return {'name1':'TutorialPoint', 'name2':'TurboGears'}

Questo modello macro.html contiene la definizione di una macro chiamata saluto. Viene utilizzato per generare un messaggio di saluto per i dati ricevuti dal controller.

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
	
   <body>
      <h2>py:def example</h2>
		
      <div>
         <div py:def = "greeting(name)">
            Hello, Welcome to ${name}!
         </div>
				
         <b>
            ${greeting(name1)} ${greeting(name2)}
         </b>
			
      </div>
   </body>
</html>

Avvia il server utilizzando gearbox

gearbox serve –reload –debug

Richiama il controller macro () inserendo il seguente URL nel browser -

http://localhost:8080/macro

Il seguente output verrà visualizzato nel browser:

py: con

Questa direttiva consente di assegnare espressioni a variabili locali. Queste variabili locali rendono l'espressione all'interno meno prolissa e più efficiente.

Supponendo che x = 50 sia fornito nei dati di contesto per un modello, il seguente sarà il py: con direttiva -

<div>
   <span py:with = "y = 50; z = x+y">$x $y $z</span>
</div>

Risulterà nel seguente output:

50 50 100

Una versione alternativa per py: è disponibile anche con direttiva -

<div>
   <py:with = "y = 50; z = x+y">$x $y $z</py:with>
</div>

Nell'esempio seguente, il controller macro () restituisce un oggetto dict con chiavi name, phy e maths.

from hello.lib.base import BaseController
from tg import expose, request

class RootController(BaseController):
   @expose('hello.templates.macro')
   def macro(self):
      return {'name':'XYZ', 'phy':60, 'maths':70}

Il modello macro.html aggiunge i valori delle chiavi phy e matematiche utilizzando py: with direttiva.

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
	
   <body>
      <h2>py:with example</h2>
      <h3>Marks Statement for : ${name}!</h3> <b>Phy: $phy Maths: $maths <span py:with = "ttl = phy+maths">Total: $ttl</span>
      </b>
		
   </body>
	
</html>

Il browser visualizzerà il seguente output in risposta all'URL http://localhost:8080/macro

Direttive sulla manipolazione della struttura

Il py:attrs la direttiva aggiunge, modifica o rimuove gli attributi dall'elemento.

<ul>
   <li py:attrs = "foo">Bar</li>
</ul>

Se foo = {‘class’:’collapse’} è presente in un contesto di modello, che verrà visualizzato dallo snippet di cui sopra.

<ul>
   <li class = "collapse">Bar</li>
</ul>

Il py:content direttiva sostituisce qualsiasi contenuto annidato con il risultato della valutazione dell'espressione -

<ul>
   <li py:content = "bar">Hello</li>
</ul>

Dato bar = 'Bye' nei dati di contesto, questo produrrebbe

<ul>
   <li>Bye</li>
</ul>

Il py:replace direttiva sostituisce l'elemento stesso con il risultato della valutazione dell'espressione -

<div>
   <span py:replace = "bar">Hello</span>
</div>

Dato bar = 'Bye' nei dati di contesto, produrrebbe

<div>
   Bye
</div>

Il contenuto di un altro documento XML (in particolare il documento HTML) può essere incluso utilizzando i tag di inclusione nel documento corrente. Per abilitare tale inclusione, lo spazio dei nomi XInclude deve essere dichiarato nell'elemento radice del documento HTML.

<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:xi = "http://www.w3.org/2001/XInclude >

La dichiarazione precedente specifica che la direttiva include contiene ‘xi’prefisso. Per aggiungere il contenuto di un'altra pagina html nel documento corrente, usa la direttiva xi: include come segue:

<xi:include href = "somepage.html" />

Nell'esempio seguente, root.py contiene il controller include (), che espone include.html.

from hello.lib.base import BaseController
from tg import expose, request

class RootController(BaseController):
   @expose('hello.templates.include')
   def include(self):
      return {}

Intestazione e piè di pagina HTML

In include.html, lo spazio dei nomi include viene dichiarato e vengono aggiunti i contenuti di header.html e footer.html. Ecco lo script HTML di templates \ include.html -

<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:xi = "http://www.w3.org/2001/XInclude">
	
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <xi:include href = "heading.html" />
      <h2>main content </h2>
      <xi:include href = "footer.html" />
   </body>
	
</html>

Ecco il codice templates \ intestazione.html -

<html>
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <h1>This is page Header</h1>
   </body>
</html>

Quello che segue è il template \ footer.html

<html>
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <h3>This is page footer</h3>
   </body>
</html>

Avvia lo sviluppo utilizzando un cambio ed entra http://localhost:8080/includenel browser. L'output renderizzato sarà come mostrato di seguito:

In questo modo è possibile ottenere la costruzione modulare delle viste. Se la risorsa menzionata nella direttiva xi: include non è disponibile, verrà generato un errore. In tal caso, una risorsa alternativa può essere caricata utilizzando xi: fallback.

<xi:include href = “main.html”>
   <xi:fallback href = ”default.html”/>
</xi.include>

L'inclusione del contenuto può essere resa dinamica come attributo href che può contenere espressioni.

Aggiungi il seguente controller in root.py.

@expose('hello.templates.ref-include')
   def refinclude(self):
      return {'pages':['heading','main','footer']}

Salva il codice seguente come ref-include.html nella cartella dei modelli.

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   xmlns:xi = "http://www.w3.org/2001/XInclude">
	
   <head>
      <title>TurboGears Templating Example</title>
   </head>
	
   <body>
      <xi:include href = "${name}.html" py:for = "name in pages" />
   </body>
	
</html>

Prima di avviare il server assicurati che la cartella dei modelli abbia un header.html, main.html e footer.html. accederehttp://localhost:8082/refinclude nel browser per ottenere il seguente output

Il @expose()decorator per impostazione predefinita esegue il rendering del contenuto html. Tuttavia, questo può essere impostato sujson content type. TurboGears supporta il rendering json tramitetg.jsonify.JSONEncoder (**kwargs)classe. Per eseguire il rendering dei dati json è sufficiente passare json come tipo di contenuto per esporre decorator.

@expose('json')
def jsondata(self, **kwargs):
   return dict(hello = 'World')

Se l'URL "/ jsondata" viene inserito nel browser, risponderà mostrando:

{"hello": "World"}

jsonp Rendering

jsonp sta per json con imbottitura. Funziona in modo simile all'output json tranne per il fatto che fornisce una risposta application / javascript con una chiamata a una funzione javascript fornendo tutti i valori restituiti dal controller come argomenti della funzione.

Per abilitare il rendering jsonp devi prima aggiungerlo all'elenco dei motori richiesti all'interno della tua applicazione - config/app_cfg.py -

base_config.renderers.append('jsonp')

Scrivi il tuo decoratore di esposizioni come segue:

@expose('json')
@expose('jsonp')
def jsonpdata (self, **kwargs): 
   return dict(hello = 'World')

Quando accedi a / jsonpdata? Callback = callme, dovresti vedere -

callme({"hello": "World"});

A volte, un'applicazione web può richiedere una struttura URL con più di un livello. TurboGears può attraversare la gerarchia degli oggetti per trovare il metodo appropriato in grado di gestire la tua richiesta.

Un progetto "avviato rapidamente" con gearbox ha una classe BaseController nella cartella lib del progetto. È disponibile come "Hello / hello / lib / base.py". Serve come classe base per tutti i sub controller. Per aggiungere un livello secondario di URL nell'applicazione, progettare una sottoclasse chiamata BlogController derivata da BaseController.

Questo BlogController ha due funzioni del controller, index () e post (). Entrambi sono progettati per esporre un modello ciascuno, blog.html e post.html.

Note - Questi modelli vengono inseriti in una sottocartella - modelli / blog

class BlogController(BaseController):

   @expose('hello.templates.blog.blog')
   def index(self):
      return {}
		
   @expose('hello.templates.blog.post')
   def post(self):
      from datetime import date
      now = date.today().strftime("%d-%m-%y")
      return {'date':now}

Ora dichiara un oggetto di questa classe nella classe RootController (in root.py) come segue:

class RootController(BaseController):
   blog = BlogController()

Altre funzioni del controller per gli URL di primo livello saranno presenti in questa classe come in precedenza.

Quando un URL http://localhost:8080/blog/viene inserito, verrà mappato alla funzione controller index () all'interno della classe BlogController. Allo stesso modo,http://localhost:8080/blog/post invocherà la funzione post ().

Il codice per blog.html e post.html è il seguente:

Blog.html

<html>
   <body>
      <h2>My Blog</h2>
   </body>
</html>

post.html

<html>
   <body>
      <h2>My new post dated $date</h2>
   </body>
</html>

Quando un URL http://localhost:8080/blog/ viene inserito, produrrà il seguente output:

Quando un URL http://localhost:8080/blog/post viene inserito, produrrà il seguente output:

Uno degli aspetti più essenziali di qualsiasi applicazione web è presentare l'interfaccia utente per un utente. HTML fornisce un tag <form> che viene utilizzato per progettare un'interfaccia. Gli elementi del modulo come input di testo, radio, select ecc. Possono essere utilizzati in modo appropriato. I dati inseriti dall'utente vengono inviati sotto forma di messaggio di richiesta HTTP allo script lato server tramite il metodo GET o POST.

Lo script lato server deve ricreare gli elementi del modulo dai dati della richiesta http. Quindi, in questo effetto, gli elementi del modulo devono essere definiti due volte: una volta in HTML e di nuovo nello script lato server.

Un altro svantaggio dell'utilizzo di form HTML è che è difficile (se non impossibile) rendere dinamicamente gli elementi del form. L'HTML stesso non fornisce alcun modo per convalidare l'input dell'utente.

ToscaWidgets2

TurboGears si basa su ToscaWidgets2, una libreria flessibile per il rendering e la convalida dei moduli. Utilizzando ToscaWidgets, possiamo definire i campi del modulo nel nostro script Python e renderli utilizzando un modello HTML. È anche possibile applicare la convalida al campo tw2.

La libreria ToscaWidgets è una raccolta di molti moduli. Alcuni moduli importanti sono elencati di seguito:

  • tw2.core- Fornisce funzionalità di base. I widget in questo modulo non sono pensati per essere disponibili per l'utente finale.

  • tw2.forms- Questa è una libreria di moduli di base. Contiene widget per campi, insiemi di campi e moduli.

  • tw2.dynforms - Contiene la funzionalità dei moduli dinamici.

  • tw2.sqla - Questa è un'interfaccia per il database SQLAlchemy.

tw2.forms

Contiene una classe Form, che funge da base per i moduli personalizzati. Esiste una classe TableForm utile per il rendering dei campi in una tabella a due colonne. ListForm presenta i suoi campi in un elenco non ordinato.

Sr.No. Campi e descrizione
1

TextField

Un campo di immissione di testo a riga singola

2

TextArea

Campo di immissione di testo su più righe

3

CheckBox

Presenta una scatola rettangolare controllabile con etichetta

4

CheckBoxList

Caselle di controllo PF gruppo selezionabili in più

5

RadioButton

Un pulsante di attivazione / disattivazione per selezionare / deselezionare

6

RadioButtonList

Gruppo di pulsanti di opzione che si escludono a vicenda

7

PasswordField

Simile a Textfield ma le chiavi di input non vengono rivelate

8

CalendarDatePicker

Consente all'utente di scegliere una data

9

SubmitButton

Pulsante per inviare un modulo

10

ImageButton

Pulsante cliccabile con un'immagine in alto

11

SingleSelectField

Consente la selezione di un singolo elemento da un elenco

12

MultipleSelectField

Consente la selezione di più elementi dall'elenco

13

FileField

Campo per il caricamento del file

14

EmailField

Un campo di immissione e-mail

15

URLField

Un campo di input per inserire l'URL

16

NumberField

Una casella numerica

17

RangeField

Un cursore numerico

Nell'esempio seguente, viene costruito un modulo che utilizza alcuni di questi widget. Sebbene la maggior parte di questi widget siano definiti in tw2.forms, CalendarDateField è definito nel modulo tw2.Dynforms. Quindi entrambi questi moduli insieme a tw2.core vengono importati all'inizio -

import tw2.core as twc
import tw2.forms as twf
import tw2.dynforms as twd

Un modulo ToscaWidgets è una classe derivata da tw2.forms.formclasse base. I widget richiesti vengono inseriti all'interno di un oggetto Layout. In questo esempio,TableLayoutsi usa. I widget vengono visualizzati in una tabella a due colonne. La prima colonna mostra la didascalia e la seconda colonna mostra il campo di input o di selezione.

Un oggetto TextField viene creato utilizzando il seguente costruttore:

twf.TextField(size, value = None)

Se non menzionato, l'oggetto TextField assume una dimensione predefinita ed è inizialmente vuoto. Durante la dichiarazione dell'oggetto TextArea, è possibile menzionare il numero di righe e colonne.

twf.TextArea("",rows = 5, cols = 30)

L'oggetto NumberField è un TextField che può accettare solo cifre. Le frecce su e giù vengono generate sul bordo destro per aumentare o diminuire il numero al suo interno. Il valore iniziale può anche essere specificato come argomento nel costruttore.

twf.NumberField(value)

Appena a destra di una casella CalendarDatePicker, viene visualizzato un pulsante del calendario. Quando viene premuto, viene visualizzato un selettore della data. L'utente può digitare manualmente una data nella casella o selezionarla dal selettore della data.

twd.CalendarDatePicker()

L'oggetto EmailField presenta un TextField, ma il testo in esso deve essere in formato e-mail.

EmailID = twf.EmailField()

Il modulo seguente ha anche un RadioButtonList. Il costruttore di questa classe contiene un oggetto List come valore del parametro options. Verrà visualizzato un pulsante di opzione per ciascuna opzione. La selezione predefinita viene specificata con il parametro value.

twf.RadioButtonList(options = ["option1","option2"],value = option1)

CheckBoxList esegue il rendering delle caselle di controllo per ciascuna opzione nell'elenco.

twf.CheckBoxList(options = [option1, option2, option3])

L'elenco a discesa è chiamato come campo SingleSelect in questa libreria ToscaWidgets. Gli elementi in un oggetto Elenco corrispondenti al parametro delle opzioni formano l'elenco a discesa. La didascalia visibile è impostata come valore del parametro prompt_text.

twf.SingleSelectField(prompt_text = 'text', options=['item1', 'item2', 'item3'])

Per impostazione predefinita, il modulo visualizza un pulsante Invia con la didascalia "salva". Per visualizzare un'altra didascalia, creare un oggetto SubmitButton e specificarlo come parametro valore.

twf.SubmitButton(value = 'Submit')

Il modulo viene inviato a un URL, che è specificato come valore del parametro di azione del modulo. Per impostazione predefinita, i dati del modulo vengono inviati tramite il metodo http POST.

action = 'URL'

Nel codice seguente, un modulo denominato AdmissionForm è progettato utilizzando i widget spiegati sopra. Aggiungi questo codice in root.py prima della classe RootController.

class AdmissionForm(twf.Form):
   class child(twf.TableLayout):
      NameOfStudent = twf.TextField(size = 20)
      AddressForCorrespondance = twf.TextArea("", rows = 5, cols = 30)
      PINCODE = twf.NumberField(value = 431602)
      DateOfBirth = twd.CalendarDatePicker()
      EmailID = twf.EmailField()
      Gender = twf.RadioButtonList(options = ["Male","Female"],value = 'Male')
      Subjects = twf.CheckBoxList(options = ['TurboGears', 'Flask', 'Django', 'Pyramid'])

      MediumOfInstruction = twf.SingleSelectField(prompt_text = 'choose',
         options = ['English', 'Hindi', 'Marathi', 'Telugu'])
			
      action = '/save_form'
      submit = twf.SubmitButton(value ='Submit')

Ora salva questo codice qui sotto come twform.html nella directory dei modelli -

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
   
   <head>
      <title>TurboGears Form Example</title>
   </head>
   
   <body>
      <div id = "tw form">
         ${form.display(value = dict(title = 'default title'))}
      </div>
   </body>
   
</html>

Nella classe RootController (in root.py), aggiungi la seguente funzione del controller:

@expose('hello.templates.twform')
def twform(self, *args, **kw):
   return dict(page = 'twform', form = MovieForm)

Nella classe AdmissionForm, abbiamo stipulated/save_formcome URL di azione. Quindi aggiungisave_form() funzione in RootController.

@expose()
def save_movie(self, **kw):
   return str(kw)

Assicurati che il server sia in esecuzione (utilizzando gearbox serve). accederehttp://localhost:8080/twform nel browser.

Premendo il pulsante di invio invierà questi dati a save_form() URL, che visualizzerà i dati del modulo sotto forma di un oggetto dizionario.

{
   'EmailID': u'[email protected]', 
   'NameOfStudent': u'Malhar Lathkar', 
   'Gender': u'Male', 
   'PINCODE': u'431602', 
   'DateOfBirth': u'2015-12-29', 
   'Subjects': [u'TurboGears', u'Flask', u'Django'], 
   'MediumOfInstruction': u'', 
   'AddressForCorrespondance': u'Shivaji Nagar\r\nNanded\r\nMaharashtra'
}

Una buona libreria di widget di Form dovrebbe avere una funzione di convalida dell'input. Ad esempio, l'utente dovrebbe essere costretto a inserire i dati in un campo obbligatorio o verificare se un campo di posta elettronica contiene un'e-mail valida, senza ricorrere ad altri mezzi programmatici (come la funzione JavaScript) per la convalida.

Le prime versioni di ToscaWidgets Forms Library utilizzavano il modulo FormEncode per il supporto della convalida. ToscaWidgets2 ora ha il supporto di convalida integrato disponibile nel modulo tw2.core. Tuttavia, è ancora possibile utilizzare le tecniche di convalida FormEncode.

Per sottoporre a convalida un modulo ToscaWidgets, viene utilizzato @validate decorator.

@validate(form, error_handler, validators)
  • Il ’form’ è l'oggetto form di ToscaWidgets da convalidare.

  • Il ‘error-handler’ è il metodo del controller utilizzato per gestire gli errori del modulo.

  • Il ‘validators’ sono un oggetto dizionario contenente validatori FormEncode.

Tipi di validatori

Il modulo tw2.core contiene una classe validatore da cui vengono ereditati altri validatori. È anche possibile progettare un validatore personalizzato basato su di esso. Alcuni dei validatori importanti sono descritti di seguito:

LengthValidator- Verificare se un valore ha una lunghezza prescritta. I limiti minimo e massimo sono definiti con i parametri minimo e massimo. I messaggi personalizzati per la lunghezza inferiore e superiore a min e max possono essere specificati come parametro tooshort e toolong.

tw2.core.LengthValidator(min = minval, max = maxval, 
   msgs = { 'tooshort': (‘message for short length’), 
   'toolong': (‘message for long length)})

RangeValidator- Solitamente utilizzato insieme a RangeField. È utile per convalidare il valore di un campo numerico entro i limiti minimo e massimo. I messaggi per i parametri tooshort e toolong possono essere personalizzati.

tw2.core.RangeValidator(min = minval, max = maxval, 
   msgs = { 'tooshort': (‘message for short length’), 
   'toolong': (‘message for long length)})

IntValidator- Questa classe è derivata da RangeValidator. Viene normalmente utilizzato per convalidare se l'input in un normale campo di testo contiene dati interi. È possibile impostare limiti minimo e massimo nonché messaggi di errore. Inoltre, il messaggio di errore per l'input non intero può essere specificato come parametro "notint".

tw2.core.IntValidator(msgs = {‘notint’:’Must be Integer’})

OneOfValidator - Questo validatore forza l'utente a selezionare un valore solo dalle opzioni disponibili nell'elenco.

tw2.core.OneOfValidator(values = [option1, option2,..], 
   msgs = {‘notinlist’:’Not in List’}}

DateValidator- Molto utile per garantire che l'input dell'utente sia una data valida. Il formato della data (l'impostazione predefinita è YMD) e il messaggio di errore sono personalizzabili. È inoltre possibile specificare limiti di data minimi e massimi. DateTimeValidator è anche disponibile per verificare l'oggetto della classe DateTime.

tw2.core.DateValidator(msgs = {format = ’%Y-%m-%d’, 
   'baddatetime': ('baddate', ('Must follow date format $format_str'))}

EmailValidator- Convalida l'input dell'utente rispetto a un indirizzo e-mail valido. Questa classe viene ereditata da un RegexValidator più generale.

tw2.core.EmailValidator(msgs = {'badregex': ('bademail', 
   ('Must be a valid email address')) }

UrlValidator- Questa classe viene ereditata anche da RegexValidator. Convalida l'input dell'utente per un URL valido.

tw2.core.UrlValidator(msgs = {'badregex': ('badurl', ('Must be a valid URL’)) }

MatchValidator- Conferma se il valore di un campo è abbinato all'altro. Ciò è particolarmente utile quando l'utente è tenuto a scegliere e confermare un campo password. L'utilizzo tipico di MatchValidator è mostrato di seguito:

import tw2.core as twc
import tw2.forms as twf
  
  class AdmissionForm(twf.Form):
      class child(twf.TableLayout):
         validator = twc.MatchValidator('pw', 'pwconfirm')
         pw = twf.PasswordField()
         pwconfirm = twf.PasswordField()

È anche possibile costruire un validatore composto, in cui si desidera che la convalida abbia successo, se uno qualsiasi dei controlli viene superato. In altri casi, potresti volere che la convalida abbia esito positivo, solo se l'input supera tutti i controlli. Per questo, tw2.core fornisce i validatori Any e All, che sono sottoclassi del CompoundValidator estendibile.

TurboGears fornisce un sistema di messaggistica molto conveniente per notificare le informazioni all'utente in modo non invadente. La classe TGFlash nel modulo tg fornisce il supporto per i messaggi lampeggianti memorizzati in un semplice cookie. Questa classe supporta il recupero dei messaggi flash sul lato server e sul lato client tramite JavaScript.

Il render()Il metodo della classe TGFlash, se usato da Python stesso, può essere invocato dal template per rendere un messaggio flash. Se utilizzato su JavaScript, fornisce un oggetto WebFlash. Esponepayload() e render() metodi per recuperare il messaggio flash corrente e renderlo da JavaScript.

Quando un progetto TurboGears viene creato utilizzando "avvio rapido", ha un modello Master.html. Contiene la definizione di una variabile di quell'oggetto flash. Il contenuto di questo messaggio flash ricevuto dal controller sostituisce il segnaposto contrassegnato in questo modello.

<py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)">
   <div py:if = "flash" py:replace = "Markup(flash)" />
</py:with>

Il tg.flash_obj è l'oggetto WebFlash, disponibile all'interno di qualsiasi modello renderizzato includendo master.htmlmodello. Questo oggetto permette di recuperare il messaggio flash corrente e visualizzarlo.

I messaggi Flash vengono memorizzati in un cookie (il cui nome per impostazione predefinita è webflash) utilizzando tg.flash()metodo. Il messaggio e i parametri di stato vengono quindi passati ad esso.

tg.flash('Message', 'status')

Se il metodo chiamato flash esegue un reindirizzamento, il flash sarà visibile all'interno della pagina reindirizzata. Se il metodo espone direttamente un modello, il flash sarà visibile all'interno del modello stesso.

L'aspetto del messaggio flash può essere personalizzato applicando lo stile CSS al codice di stato. Un progetto "quickstarted" contiene errori, avvertenze, informazioni e codici di stato ok personalizzati da un foglio di stile public / css / style.css. È inoltre possibile aggiungere più codici di stato con stili.

#flash > .warning {
   color: #c09853;
   background-color: #fcf8e3;
   border-color: #fbeed5;
}

#flash > .ok {
   color: #468847;
   background-color: #dff0d8;
   border-color: #d6e9c6;
}

#flash > .error {
   color: #b94a48;
   background-color: #f2dede;
   border-color: #eed3d7;
}

#flash > .info {
   color: #3a87ad;
   background-color: #d9edf7;
   border-color: #bce8f1;
}

Questo foglio di stile esterno deve essere incluso nel modello -

<link rel = "stylesheet" type = "text/css" media = "screen" 
   href = "${tg.url('/css/style.css')}" />

La configurazione di qualsiasi supporto per messaggi Flash può essere ottenuta impostando i parametri per il metodo configure () dell'oggetto TGFlash o in app_cfg.py (nella cartella config). I parametri configurabili sono:

Sr.No. Parametri e descrizione
1

flash.cookie_name

Nome del cookie utilizzato per memorizzare i messaggi flash. L'impostazione predefinita èwebflash.

2

flash.default_status

Stato del messaggio predefinito se non specificato (ok per impostazione predefinita)

3

flash.template

Usato come flash template quando reso.

4

flash.allow_html

Giri on/off escaping in flash messages, per impostazione predefinita HTML non è consentito.

5

flash.js_call

Codice JavaScript che verrà eseguito durante la visualizzazione del flash da JavaScript. L'impostazione predefinita èwebflash.render()

6

flash.js_template

string.Template istanza utilizzata per sostituire il supporto JavaScript completo per i messaggi flash.

  • pop_payload() - funzione fetches current flash message, statuse informazioni correlate. Ottenere il messaggio flash cancellerà il cookie.

  • render(container_id, use_js=True) - Rendere il messaggio flash all'interno del modello o fornire supporto Javascript per loro.

  • container_id è il DIV in cui verranno visualizzati i messaggi, mentre use_js alterna il rendering del flash come HTML o l'utilizzo di JavaScript.

  • status - Ottieni solo lo stato di flash corrente, ottenere lo stato di flash eliminerà il cookie.

  • message - Ottieni solo il messaggio flash corrente, ottenere il messaggio flash cancellerà il cookie.

Come creare un semplice messaggio flash?

Nell'esempio seguente, viene fornito un metodo flash () nella classe del controller principale. Chiama un messaggio flash () che viene visualizzato nel template esposto, flash.html

from hello.lib.base import BaseController
from tg import expose, flash, redirect, request

class RootController(BaseController):
   @expose('hello.templates.flash')
   def flash(self, user = None):
      
      if user:
         flash(message = "Welcome "+user,status = "ok")
      else:
         flash(message = "Welcome Guest",status = "info")
      return {}

Il codice per fare flash.html nella cartella dei modelli è la seguente

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   xmlns:xi = "http://www.w3.org/2001/XInclude">

   <head>
      <title>TurboGears 2.3: Flash messages>/title>
      <link rel = "stylesheet" type = "text/css" media = "screen"
         href = "${tg.url('/css/style.css')}" />
			
      <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)">
         <div py:if = "flash" py:replace = "Markup(flash)" />
      </py:with>
		
   </head>

   <body>
      <h2>Hello TurboGears</h2>
   </body>
	
</html>

Avvia il server ed entra http://localhost:8080/flash?user=MVL nel browser

Cambia URL in http://localhost:8080/flash e vedere il messaggio flash formattato in modo diverso come da definizione in style.css

Spesso è necessario conservare semplici dati di navigazione allegati al browser di un utente. Le sessioni sono la tecnica più comunemente usata. La sessione rappresenta i dati che non devono essere memorizzati in una forma più persistente come il file su disco o il database.

Tuttavia, i dati di sessione in TurboGears possono essere supportati da valori di file system, database o cookie con hash. Una piccola quantità di dati di sessione viene generalmente conservata nei cookie, ma per il volume maggiore di dati di sessione viene utilizzato MemCache.

MemCache è un demone a livello di sistema. Fornisce un accesso rapido ai dati memorizzati nella cache ed è estremamente scalabile. Tuttavia, è inteso per essere utilizzato solo su server sicuri e quindi deve essere mantenuto e protetto da sysadmin.

Becher nella gestione delle sessioni

TurboGears utilizza Beaker per la gestione delle sessioni. Un progetto avviato rapidamente da Gearbox è configurato per impostazione predefinita per utilizzare cookie con hash per memorizzare i dati della sessione.

Ogni volta che un client si connette, il middleware della sessione (Beaker) ispezionerà il cookie utilizzando il nome del cookie, che è stato definito nel file di configurazione. Se il cookie non viene trovato, verrà impostato nel browser. In tutte le visite successive, il middleware troverà il cookie e lo utilizzerà.

Per abilitare la gestione della sessione, la classe di sessione dovrebbe essere incorporata nel progetto seguendo l'istruzione import:

from tg import session

Per salvare i dati in una variabile di sessione -

session[‘key’] = value
session.save()

Per recuperare la variabile di sessione -

return session[‘key’]

Tieni presente che devi salvare esplicitamente la sessione affinché le tue chiavi vengano memorizzate in quella sessione.

Il delete() il metodo dell'oggetto sessione cancellerà tutte le sessioni utente -

session.delete()

Anche se non è consuetudine eliminare tutte le sessioni utente in un determinato ambiente di produzione, in genere lo farai per la pulizia dopo che sono stati eseguiti test di usabilità o funzionali.

Di seguito è riportato un semplice esempio per dimostrare le sessioni. La classe RootController ha un'estensionesetsession() metodo che imposta una variabile di sessione.

from hello.lib.base import BaseController
from tg import expose, session
class RootController(BaseController):
   
   @expose()
   def setsession(self):
      session['user'] = 'MVL'
      session.save()
      
      str = "<b>sessionVariable set to "+session['user'] 
      str = str+"<br><a href = '/getsession'>click here to retrieve</a></b>"
      return str
   
   @expose()
   def getsession(self):
      return "<b>value of session variable retrieved " +session['user'] +"</b>"

accedere http://localhost:8080/setsession

Un collegamento nel browser porta a http://localhost:8080/getsession che recupera e visualizza la variabile di sessione -

Per migliorare le prestazioni di un'applicazione web, soprattutto se è coinvolta in operazioni lunghe, vengono utilizzate tecniche di caching. TurboGears fornisce due tipi di tecniche di memorizzazione nella cache:

Whole-page Caching

Funziona a livello di protocollo HTTP per evitare intere richieste al server facendo in modo che il browser dell'utente o un server proxy intermedio (come Squid) intercetti la richiesta e restituisca una copia cache del file.

Application-level Caching

Funziona all'interno del server delle applicazioni per memorizzare nella cache i valori calcolati, spesso i risultati di query di database complesse, in modo che le richieste future possano evitare di dover ricalcolare i valori. Per le applicazioni web, la memorizzazione nella cache a livello di applicazione fornisce un modo flessibile per memorizzare nella cache i risultati di query complesse in modo che il carico totale di un determinato metodo di controller possa essere ridotto a poche query specifiche dell'utente o del caso e il sovraccarico di rendering di un modello .

Caching a livello di applicazione

Come accennato in precedenza, il progetto TurboGears 'quickstarted' è configurato per abilitare il pacchetto Beaker per il supporto della cache. Beaker supporta i seguenti back-end utilizzati per l'archiviazione della cache:

  • memory- Utilizzato per l'archiviazione per processo. È estremamente veloce.

  • filesystem - archiviazione per processo e multi-processo.

  • DBM database - per processo, multi-processo, abbastanza veloce.

  • SQLAlchemy database- archiviazione per server di database. Più lento rispetto alle opzioni sopra indicate.

  • Memcached - cache basata sulla memoria multi-server.

Memorizzazione nella cache del controller

Per una rapida memorizzazione nella cache del controller, un file cached()decoratore è disponibile. L'intero corpo del controller viene memorizzato nella cache in base a vari parametri di richiesta. La definizione ditg.decorators.cached() decoratore è il seguente

tg.decorators.cached(key, expire, type, 
   query-args, cache_headers, invalidate_on_startup, cache_response)

La descrizione dei parametri è la seguente:

Sr.No. Parametri e descrizione
1

key

Specifica i parametri del controller utilizzati per generare la chiave della cache.

2

expire

Tempo in secondi prima che la cache scada, il valore predefinito è "mai".

3

Type

dbm, memoria, file, memcached o Nessuno.

4

cache_headers

Una tupla di nomi di intestazione che indicano le intestazioni di risposta.

5

invalidate_on_startup

Se True, la cache viene invalidata ogni volta che l'applicazione viene avviata o riavviata.

6

cache_response

la risposta deve essere memorizzata nella cache o meno, il valore predefinito è True.

Di seguito è riportato un esempio di memorizzazione nella cache del controller:

@cached(expire = 100, type = 'memory')
@expose()
def simple(self):
   return "This is a cached controller!"

Caching a livello di modello

Il motore di modelli Genshi recupera il modello da una cache se il suo contenuto non è cambiato. La dimensione predefinita di questa cache è 25. Per impostazione predefinita, il ricaricamento automatico dei modelli è vero. Per migliorare le prestazioni, è possibile effettuare le seguenti impostazioni inapp_cfg.py -

[app:main]
genshi.max_cache_size = 100
auto_reload_templates = false

Per memorizzare un modello nella cache, devi solo restituire il file tg_cache opzione dal controller che esegue il rendering del modello memorizzato nella cache.

Tg_cache è un dizionario che accetta le seguenti chiavi:

  • key - La chiave della cache. Default: Nessuna.

  • expire - per quanto tempo la cache deve rimanere in vita. Default: non scade mai

  • type - memoria, dbm, memcached. Default: dbm.

L'esempio seguente illustra la memorizzazione nella cache dei modelli:

@expose(hello.templates.user')
def user(self, username):
   return dict(user = username, tg_cache = dict(key = user, expire = 900))

Sebbene sia possibile utilizzare SQL nell'applicazione TurboGears per eseguire operazioni CRUD su qualsiasi database relazionale, è consigliabile utilizzare SQLAlchemy, un toolkit Python è un potente Object Relation Mapper che offre agli sviluppatori di applicazioni la piena potenza e flessibilità di SQL. Oltre al supporto per database basati su SQL tramite SQLAlchemy, TurboGears supporta anche database MongoDB tramite Ming. In questa sezione viene discussa la funzionalità di SQLAlchemy.

Cos'è ORM (Object Relational Mapping)?

La maggior parte delle piattaforme del linguaggio di programmazione sono orientate agli oggetti. I dati nei server RDBMS d'altra parte vengono memorizzati come tabelle. La mappatura delle relazioni tra oggetti è una tecnica per mappare i parametri degli oggetti alla struttura della tabella RDBMS sottostante. Un'API ORM fornisce metodi per eseguire operazioni CRUD senza dover scrivere istruzioni SQL non elaborate.

Quando un progetto TurboGears viene creato utilizzando il comando 'avvio rapido' dal toolkit del cambio, il supporto SQLAlchemy è abilitato per impostazione predefinita dalle seguenti impostazioni di configurazione:

config['use_sqlalchemy'] = True
config['sqlalchemy.url'] = 'sqlite:///devdata.db'

Il progetto "avvio rapido" crea anche un pacchetto di modelli al suo interno. Ad esempio, un progetto "Hello" avrà Hello \ hello \ model. I seguenti file vengono creati in questo pacchetto:

  • __init__.py- Qui è dove viene impostato l'accesso al database. Gli oggetti del modello dell'applicazione vengono importati in questo modulo. Ha anche una DBSession, un gestore di sessioni globale e anche una DeclarativeBase, che è una classe base per tutte le classi del modello.

  • auth.py- Qui è dove vengono definiti i modelli utilizzati dallo stack di autenticazione. Ulteriori modelli di database sono archiviati in questo pacchetto, come modulo separato, e aggiunti in __init__.py.

Aggiungiamo un modello studente che creerà una tabella studenti nel nostro file sqlite Banca dati.

Hello\hello\model\student.py

from sqlalchemy import *
from sqlalchemy.orm import mapper, relation, relation, backref
from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode, DateTime

from hello.model import DeclarativeBase, metadata, DBSession
from datetime import datetime

class student(DeclarativeBase):
   __tablename__ = 'student'

   uid = Column(Integer, primary_key = True)
   name = Column(Unicode(20), nullable = False, default = '')
   city = Column(Unicode(20), nullable = False, default = '')
   address = Column(Unicode(100), nullable = False, default = '')
   pincode = Column(Unicode(10), nullable = False, default = '')

Ora aggiungi questo modello init_model() funzione all'interno __init__.py.Questa funzione contiene già il modello di autenticazione. Aggiungi il nostro modello di studente sotto di esso.

# Import your model modules here.
from hello.model.auth import User, Group, Permission
from hello.model.student import student

Se vuoi che la tabella venga inizializzata con alcuni dati al momento della configurazione dei modelli, aggiungila in bootstrap.py nel pacchetto websetup. Aggiungi le seguenti istruzioni nel filebootstrap() funzione.

s1 = model.student()
s1.name = 'M.V.Lathkar'
s1.city = 'Nanded'
s1.address = 'Shivaji Nagar'
s1.pincode = '431602'

model.DBSession.add(s1)
model.DBSession.flush()
transaction.commit()

I modelli vengono inizializzati eseguendo il comando setup-app del cambio -

gearbox setup-app

L'oggetto Session di SQLAlchemy gestisce tutte le operazioni di persistenza dell'oggetto ORM.

I seguenti metodi di sessione eseguono operazioni CRUD:

  • DBSession.add(model object) - inserisce un record nella tabella mappata.

  • DBSession.delete(model object) - elimina il record dalla tabella.

  • DBSession.query(model).all() - recupera tutti i record dalla tabella (corrispondente a una query SELECT).

È possibile applicare il filtro al set di record recuperato utilizzando un attributo di filtro. Ad esempio, per recuperare i record con city = 'Hyderabad' nella tabella degli studenti, utilizza la seguente dichiarazione:

DBSession.query(model.student).filter_by(city = ’Hyderabad’).all()

Vedremo ora come interagire con i modelli tramite gli URL del controller.

Per prima cosa progettiamo un modulo ToscaWidgets per l'inserimento dei dati dello studente

Hello\hello\controllers.studentform.py

import tw2.core as twc
import tw2.forms as twf

class StudentForm(twf.Form):
   class child(twf.TableLayout):
      name = twf.TextField(size = 20)
      city = twf.TextField()
      address = twf.TextArea("",rows = 5, cols = 30)
      pincode = twf.NumberField()

   action = '/save_record'
   submit = twf.SubmitButton(value = 'Submit')

Nel RootController (root.py dell'applicazione Hello), aggiungi la seguente funzione di mapping '/ add' URL -

from hello.controllers.studentform import StudentForm

class RootController(BaseController):
   @expose('hello.templates.studentform')
   def add(self, *args, **kw):
      return dict(page='studentform', form = StudentForm)

Salva il seguente codice HTML come studentform.html nella cartella dei modelli -

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
   
   <head>
      <title>Student Registration Form</title>
   </head>
   
   <body>
      <div id = "getting_started">
         ${form.display(value = dict(title = 'Enter data'))}
      </div>
   </body>

</html>

accedere http://localhost:8080/addnel browser dopo aver avviato il server. Il seguente modulo di informazioni sullo studente si aprirà nel browser:

Il modulo sopra è progettato per essere inviato al ‘/save_record’URL. Quindi asave_record() la funzione deve essere aggiunta nel file root.pyper esporlo. I dati dello studentform vengono ricevuti da questa funzione come filedict()oggetto. Viene utilizzato per aggiungere un nuovo record nella tabella studenti sottostante il modello studente.

@expose()
#@validate(form = AdmissionForm, error_handler = index1)

def save_record(self, **kw):
   newstudent = student(name = kw['name'],city = kw['city'],
      address = kw['address'], pincode = kw['pincode'])
   DBSession.add(newstudent)
   flash(message = "new entry added successfully")
   redirect("/listrec")

Si noti che dopo l'aggiunta con successo, il browser verrà reindirizzato a ‘/listrec’ URL. Questo URL è esposto da un filelistrec() function. Questa funzione seleziona tutti i record nella tabella studenti e li invia sotto forma di oggetto dict al modello studentlist.html. Questolistrec() la funzione è la seguente:

@expose ("hello.templates.studentlist")
def listrec(self):
   entries = DBSession.query(student).all()
   return dict(entries = entries)

Il modello studentlist.html scorre l'oggetto dizionario delle voci utilizzando py: for Directive. Il modello studentlist.html è il seguente:

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/">
   
   <head>
      <link rel = "stylesheet" type = "text/css" media = "screen" 
         href = "${tg.url('/css/style.css')}" />
      <title>Welcome to TurboGears</title>
   </head>
   
   <body>
      <h1>Welcome to TurboGears</h1>
      
      <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)">
         <div py:if = "flash" py:replace = "Markup(flash)" />
      </py:with>
      
      <h2>Current Entries</h2>
      
      <table border = '1'>
         <thead>
            <tr>
               <th>Name</th>
               <th>City</th>
               <th>Address</th>
               <th>Pincode</th>
            </tr>
         </thead>
         
         <tbody>
            <py:for each = "entry in entries">
               <tr>
                  <td>${entry.name}</td> <td>${entry.city}</td>
                  <td>${entry.address}</td> <td>${entry.pincode}</td>
               </tr>
            </py:for>
         </tbody>
         
      </table>
   
   </body>
</html>

Ora rivisita il file http://localhost:8080/adde inserisci i dati nel modulo. Facendo clic sul pulsante di invio, il browser porterà a studentlist.html. Inoltre lampeggerà un messaggio "nuovo record aggiunto con successo".

ToscaWidgets contiene un controllo DataGrid che fornisce un modo rapido per presentare i dati in forma tabulare. L'oggetto DataGrid viene dichiarato come segue:

from tw2.forms import DataGrid
student_grid = DataGrid(fields = [('Name', 'name'),('City', 'city'),
   ('Address','address'), ('PINCODE', 'pincode')])

Ora, la funzione showgrid () recupera tutti i record nella tabella degli studenti ed espone i dati al modello grid.html. Di seguito viene fornito prima il codice per la funzione showgrid () e quindi il codice grid.html:

showgrid ()

@expose('hello.templates.grid')
def showgrid(self):
   data = DBSession.query(student).all()
   return dict(page = 'grid', grid = student_grid, data = data)

grid.html

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
   
   <head>
      <title>Student Registration Form</title>
   </head>
   
   <body>
      <div id = "getting_started">
         <div>${grid.display(value = data)}</div>
      </div>
   </body>

</html>

I seguenti dati tabulari verranno visualizzati quando http://localhost:8080/showlist L'URL è inserito nel browser -

TurboGears fornisce un comodo decoratore chiamato paginate () per dividere l'output nelle pagine. Questo decoratore è combinato con il decoratore expose (). Il decoratore @Paginate () accetta l'oggetto dizionario del risultato della query come argomento. Inoltre, il numero di record per pagina viene deciso dal valore dell'attributo items_per_page. Assicurati di importare la funzione di impaginazione da tg.decorators nel tuo codice.

Riscrivi la funzione listrec () in root.py come segue:

from tg.decorators import paginate
class RootController(BaseController):
   @expose ("hello.templates.studentlist")
   @paginate("entries", items_per_page = 3)
	
   def listrec(self):
      entries = DBSession.query(student).all()
      return dict(entries = entries)

Gli elementi per pagina sono impostati su tre.

Nel modello studentlist.html, la navigazione tra le pagine viene abilitata aggiungendo tmpl_context.paginators.entries.pager () sotto la direttiva py: for. Il codice per questo modello dovrebbe essere il seguente:

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/">
   
   <head>
      <link rel = "stylesheet" type = "text/css" media = "screen" 
         href = "${tg.url('/css/style.css')}" />
      <title>Welcome to TurboGears</title>
   </head>
   
   <body>
      
      <h1>Welcome to TurboGears</h1>
		
      <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)">
         <div py:if = "flash" py:replace = "Markup(flash)" />
      </py:with>
      
      <h2>Current Entries</h2>
		
      <table border = '1'>
         <thead>
            <tr>
               <th>Name</th>
               <th>City</th>
               <th>Address</th>
               <th>Pincode</th>
            </tr>
         </thead>
         
         <tbody>
            <py:for each = "entry in entries">
               <tr>
                  <td>${entry.name}</td> <td>${entry.city}</td>
                  <td>${entry.address}</td> <td>${entry.pincode}</td>
               </tr>
            </py:for>
				
            <div>${tmpl_context.paginators.entries.pager()}</div>
         </tbody>
         
      </table>
   
   </body>

</html>

accedere http://localhost:8080/listrecnel browser. Viene visualizzata la prima pagina di record nella tabella. In cima a questa tabella, vengono visualizzati anche i collegamenti ai numeri di pagina.

Come aggiungere il supporto dell'impaginazione a Datagrid

È anche possibile aggiungere il supporto dell'impaginazione a datagrid. Nell'esempio seguente, datagrid impaginato è progettato per visualizzare il pulsante di azione. Per attivare il pulsante di azione l'oggetto datagrid è costruito con il seguente codice:

student_grid = DataGrid(fields = [('Name', 'name'),('City', 'city'),
   ('Address','address'), ('PINCODE', 'pincode'),
   ('Action', lambda obj:genshi.Markup('<a
      href = "%s">Edit</a>' % url('/edit',
      params = dict(name = obj.name)))) ])

Qui il pulsante di azione è collegato al parametro del nome di ciascuna riga nella griglia dei dati.

Riscrivi il showgrid() funzionare come segue -

@expose('hello.templates.grid')
@paginate("data", items_per_page = 3)

def showgrid(self):
   data = DBSession.query(student).all()
   return dict(page = 'grid', grid = student_grid, data = data)

Il browser mostra datagrid impaginato come segue:

Facendo clic sul pulsante Modifica nella terza riga, verrà reindirizzato al seguente URL http://localhost:8080/edit?name=Rajesh+Patil

TurboGears fornisce l'estensione tgext.admin, che è fornita da tgext.crud e sprox. Questo Sprox è un pacchetto utilizzato per la creazione di widget web direttamente dallo schema del database. Può essere utilizzato per creare automaticamente semplici pagine di amministrazione ed è il toolkit che alimenta la pagina / admin nelle nuove applicazioni avviate rapidamente.

Per impostazione predefinita, l'amministratore fornirà un accesso generato automaticamente a tutti i modelli importati nei modelli di progetto / __ init__.py.

Come creare TurboGears Admin

L'amministratore predefinito di TurboGears viene creato come oggetto della classe AdminController -

from tgext.admin.controller import AdminController

class RootController(BaseController):
   admin = AdminController(model, DBSession, config_type = TGAdminConfig)

Questo crea un amministratore per tutti i modelli con la configurazione amministratore predefinita di TurboGears.

Tramite il manager è stato creato un utente in fase di setup. Ora è possibile accedere a TurboGears Admin all'indirizzohttp://localhost:8080/adminLa prima volta che si accede a questa pagina, verrà richiesta l'autenticazione. Puoi semplicemente fornire il nome utente e la password dell'utente che il comando setup-app ha creato per noi -

Username: manager
Password: managepass

Per accedere al progetto di avvio rapido, aggiungi le seguenti funzioni alla classe RootController (controllers / root.py).

from hello.lib.base import BaseController
from tg import expose, flash, redirect, request,url, lurl
from tg import redirect, validate
from hello import model
from hello.model import DBSession
from tgext.admin.tgadminconfig import BootstrapTGAdminConfig as TGAdminConfig
from tgext.admin.controller import AdminController
from tg.exceptions import HTTPFound

class RootController(BaseController):
   admin = AdminController(model, DBSession, config_type =  TGAdminConfig)
   
   @expose('hello.templates.index')
   def index(self):
      return dict(page = 'index')
   
   @expose('hello.templates.login')
   def login(self, came_from = lurl('/'), failure = None,    login = ''):
	
      if failure is not None:
         if failure == 'user-not-found':
            flash(_('User not found'), 'error')
         elif failure == 'invalid-password':
            flash(_('Invalid Password'), 'error')
			
      login_counter = request.environ.get('repoze.who.logins', 0)
		
      if failure is None and login_counter > 0:
         flash(_('Wrong credentials'), 'warning')
		 
      return dict(page = 'login', login_counter = str(login_counter), 
         came_from = came_from, login = login)
   @expose()
	
   def post_login(self, came_from = lurl('/')):
      if not request.identity:
         
         login_counter = request.environ.get('repoze.who.logins', 0) + 1
            redirect('/login', params = dict(came_from = came_from,
            __logins = login_counter))
		
         userid = request.identity['repoze.who.userid']
         flash(('Welcome back, %s!') % userid)
			
         return HTTPFound(location = came_from)

Accedi all'applicazione "avvio rapido" dopo aver avviato il server e visitando http://localhost:8080/logine quindi immettere le credenziali del gestore come mostrato sopra. Il browser visualizzerà una pagina di amministrazione come quella mostrata di seguito -

La pagina mostra tutti i modelli creati in questa applicazione. Puoi fare clic su qualsiasi modello per visualizzare l'elenco delle voci in esso contenute -

Il pulsante "Nuovo" in cima a questo datagrid consente di aggiungere il record. Allo stesso modo, i pulsanti di azione per la modifica e l'eliminazione di un record sono forniti anche nella colonna delle azioni di questo datagrid. Viene inoltre visualizzata una casella di ricerca per selezionare i record in modo condizionale.

Un'applicazione TurboGears viene creata dalle opzioni di avvio rapido e di configurazione dell'app del toolkit del cambio, che ha il supporto di autorizzazione e autenticazione abilitato per impostazione predefinita. I modelli dichiarati in auth.py vengono impostati e inizializzati secondo i valori assegnati in bootstrap.py.

I seguenti modelli sono dichiarati in auth.py -

Modello utente

Il modello utente contiene il design di una tabella tg_user. Questa tabella è utilizzata dal pacchetto repose.who. Questo pacchetto repose.who è una libreria di autenticazione potente ed estensibile per le applicazioni WSGI. La struttura di un modello utente è la seguente:

class User(DeclarativeBase):

"""
   __tablename__ = 'tg_user'
   
   user_id = Column(Integer, autoincrement = True, primary_key=True)
   user_name = Column(Unicode(16), unique = True, nullable = False)
   email_address = Column(Unicode(255), unique = True,nullable=False)
                                             
   display_name = Column(Unicode(255))
   _password = Column('password', Unicode(128))
   created = Column(DateTime, default = datetime.now)

Questo modello di gruppo contiene la definizione tabella tg_group. La sua definizione è data in auth.py come segue:

class Group(DeclarativeBase):
   __tablename__ = 'tg_group'
   
   group_id = Column(Integer, autoincrement = True,primary_key = True)
   group_name = Column(Unicode(16),unique = True,nullable = False)
   display_name = Column(Unicode(255))
   created = Column(DateTime, default = datetime.now)

Viene impostato anche un altro modello di autorizzazione, che contiene la definizione dell'autorizzazione.

class Permission(DeclarativeBase):
   __tablename__ = 'tg_permission'
   
   permission_id = Column(Integer,autoincrement = True,primary_key = True)
   permission_name = Column(Unicode(63), unique = True, nullable = False)
   description = Column(Unicode(255))

Al momento della configurazione dei modelli, in queste tabelle vengono aggiunti i seguenti dati:

u = model.User()
u.user_name = 'manager'
u.display_name = 'Example manager'
u.email_address = '[email protected]'
u.password = 'managepass'

model.DBSession.add(u)
g = model.Group()
g.group_name = 'managers'
g.display_name = 'Managers Group'
g.users.append(u)

model.DBSession.add(g)
p = model.Permission()
p.permission_name = 'manage'
p.description = 'This permission gives an administrative right'
p.groups.append(g)

model.DBSession.add(p)
u1 = model.User()
u1.user_name = 'editor'
u1.display_name = 'Example editor'
u1.email_address = '[email protected]'
u1.password = 'editpass'

model.DBSession.add(u1)

Modello predicato

Il modulo predicati nel pacchetto tg contiene le definizioni per i controllori dei predicati. Un predicato è una condizione che deve essere soddisfatta affinché l'utente possa accedere all'origine richiesta. Tale predicato, o condizione, può essere costituito da più predicati: quelli sono chiamati predicati composti. I controller di azione, o controller, possono avere un solo predicato, sia esso singolo o composto.

Se un utente non è connesso o non dispone delle autorizzazioni appropriate, questo verificatore di predicati genera un 401 (HTTP non autorizzato), che viene rilevato dal middleware repoze.who per visualizzare la pagina di accesso che consente all'utente di accedere e reindirizzare il l'utente torna alla pagina corretta quando hanno finito.

Le diverse condizioni o predicati definiti nel modulo tg.predicates sono:

Sr.No. Modulo e descrizione tg.predicates
1

All

Controlla se tutti i predicati specificati sono soddisfatti

2

Any

Controlla se almeno uno dei predicati specificati è soddisfatto

3

is_user

Verificare che il nome utente dell'utente autenticato sia quello specificato

4

in_group

Verifica che l'utente appartenga al gruppo specifico.

5

in_all_groups

Verificare che l'utente appartenga a tutti i gruppi specificati.

6

in_any_group

Verifica che l'utente appartenga ad almeno uno dei gruppi specificati.

7

is_anonymous

Verifica che l'utente corrente sia anonimo.

8

has_permission

Verificare che l'utente corrente disponga dell'autorizzazione specificata.

9

has_all_permissions

Verificare che all'utente corrente siano state concesse tutte le autorizzazioni specificate.

10

has_any_permission

Verifica che l'utente disponga di almeno una delle autorizzazioni specificate.

Ad esempio, se hai un predicato, che è grant access user belonging to customers group, quindi puoi utilizzare il seguente controllore dei predicati integrato:

from tg.predicates import in_group
p in_group(‘customers’)

Il seguente verificatore dei predicati concederà l'accesso all'utente "root" oa chiunque disponga dell'autorizzazione "gestisci":

from tg.predicates import Any, is_user, has_permission
p = Any(is_user('root'), has_permission('manage'), 
   sg = 'Only administrators can remove blog posts')

TurboGears supporta anche i database di documenti MongoDB. Utilizza Ming, un'API Object Document Mapper. L'utilizzo di Ming è molto simile a SQLAlchemy. Il linguaggio di query Ming rende possibile il porting del progetto TurboGears basato su SQLAlchemy su Ming.

Cos'è PyMongo

PyMongo è una distribuzione Python contenente strumenti per lavorare con MongoDB. Ming estende l'offerta di PyMongo -

  • Modelli dichiarativi
  • Convalida e conversione dello schema
  • Evoluzione dello schema
  • Implementazione di Pure InMemory MongoDB
  • Unità di lavoro
  • Mappa di identità
  • Relazioni uno-a-molti, molti-a-uno e molti-a-molti

Prima di tutto, devi scaricare e installare MongoDB. L'ultima distribuzione di MongoDB può essere scaricata dahttps://www.mongodb.org/downloads

Su Windows, avvia il server MongoDB fornendo l'opzione -dbpath -

C:\mongodb\bin>Mongod --dbpath d:\mongo

D:\mongo folderè designato per archiviare il database MongoDB. Il server inizia ad ascoltarehttp://localhost:27017. Ora per avviare la shell MongoDB usa il seguente comando:

C:\mongodb\bin>Mongo

Il nostro ambiente MongoDB è ora pronto.

Ora crea un progetto TurboGears con l'opzione -ming -

gearbox quickstart --ming Hello

Questo progetto di avvio rapido fornirà un livello di autenticazione e autorizzazione come quello fornito per la versione SQLAlchemy. Questa applicazione ora tenterà di connettersi a un server sulla porta 27017 sulla macchina locale. Il file development.ini nella cartella del progetto contiene le seguenti impostazioni:

ming.url = mongodb://localhost:27017/
ming.db = hello

Imposta il progetto utilizzando il seguente comando:

Python setup.py develop

La cartella del progetto contiene la sottocartella dei modelli che ha i seguenti file:

  • __init__.py - Qui è dove il file databasel'accesso è impostato. Le tue collezioni dovrebbero essereimported into this module. Ad esempio, aggiungeremo la raccolta studenti in questo pacchetto.

  • session.py - Questo file definisce il file session of your database connection. Dovrai importarlo ogni volta che dovrai dichiarare un fileMappedClass per specificare la sessione perform queries.

  • auth.py - Questo file verrà creato, se lo hai enabled authentication and authorizationnella guida rapida. Definisce tre collezionirepoze.who, che si basa ulteriormente su: utente, gruppo e autorizzazione.

Definizione della tua collezione

Per impostazione predefinita, TurboGears configura Ming in una modalità dichiarativa. È simile al supporto dichiarativo di SQLAlchemy e richiede che ogni modello erediti dalla classe MappedClass.

La MappedClass richiede che all'interno sia disponibile una sottoclasse __mongometa__, che fornisce ulteriormente i dettagli riguardanti il ​​nome della collezione in cui sono archiviati i documenti e la sessione utilizzata per archiviare i documenti.

MappedClass contiene anche la definizione dei campi nel documento. Il modulo odm di Ming ha definizioni di diversi tipi di proprietà del campo -

  • FieldProperty
  • ForeignIdProperty
  • RelationProperty

Il ming.schema module definisce i seguenti tipi di dati:

  • ming.schema.Anything
  • ming.schema.Array
  • ming.schema.Binary
  • ming.schema.Bool
  • ming.schema.Float
  • ming.schema.Int
  • ming.schema.ObjectId
  • ming.schema.Scalar
  • ming.schema.String

Per aggiungere la raccolta di studenti in questo modello, salva il codice seguente come student.py nella cartella hello / models.

Ciao \ models \ student.py

from ming import schema
from ming.odm import MappedClass
from ming.odm import FieldProperty, ForeignIdProperty
from hello.model import DBSession
   
Class student(MappedClass):
   class __mongometa__:
      session = DBSession
      name = 'student'
      
   _id = FieldProperty(schema.ObjectId)
   name = FieldProperty(schema.String(required = True))
   city = FieldProperty(schema.String(if_missing = ''))
   address = FieldProperty(schema.String(if_missing = ''))
   pincode = FieldProperty(schema.String(if_missing = ''))

Infine, includi questo modello in hello \ models \ __ init__.py

# Import your model modules here.
from hello.model.auth import User, Group, Permission
from hello.model.student import student

Per configurare questi modelli, eseguire il seguente comando del cambio:

Gearbox setup-app

Avvia il server con il seguente comando del cambio:

Gearbox serve –reload –debug

Apri la homepage di questa applicazione (http://localhost:8080/)e accedi con le credenziali di manager. La pagina di amministrazione di questa applicazione mostrerà l'elenco dei modelli impostati. (accedi come manager, password managepass)

La creazione di raccolte può essere verificata anche nell'interfaccia web di MongoDB e nella shell MongoDB.

ODMSession viene utilizzato per eseguire diverse operazioni sul database utilizzando le seguenti funzioni:

  • model.query.find()
  • model.query.find_and_modify()
  • model.remove()
  • model.update()
  • model.flush()

Progettazione di un modulo ToscoWidget

Progetteremo ora un modulo ToscoWidget per inserire i dati dello studente e aggiungerlo nella tabella sottostante il modello dello studente.

Di seguito è riportato il codice per creare un studentform.py -

Ciao \ controllers \ studentform.py

import tw2.core as twc
import tw2.forms as twf
   
class StudentForm(twf.Form):

   class child(twf.TableLayout):
      name = twf.TextField(size = 20)
      city = twf.TextField()
      address = twf.TextArea("",rows = 5, cols = 30)
      pincode = twf.NumberField()
		
   action = '/save_record'
   submit = twf.SubmitButton(value = 'Submit')

Nell'applicazione Rootcontroller '/ add' URL che chiama la funzione add (), che aprirà il modulo sopra progettato nel browser. Il suo pulsante di invio quindi richiama la funzione save_record (). Recupera i dati del modulo e li salva nella tabella studenti e reindirizza l'applicazione all'URL "/ listrec", che espone il modello dell'elenco degli studenti.

Il file root.py per questa attività è il seguente:

Ciao / controllers / root.py

from hello.lib.base import BaseController
from tg import expose, flash, redirect, request,url, lurl
from tg import redirect, validate
from hello import model
from hello.model import DBSession
from hello.model.student import student
   
from hello.controllers.studentform import StudentForm
   
class RootController(BaseController):
   @expose()
   def index(self):
      return "<h1>Hello World</h1>"
         
   @expose ("hello.templates.studentlist")
   def listrec(self):
      entries = student.query.find()
      return dict(entries = entries)
               
   @expose('hello.templates.studentform')
   def add(self, *args, **kw):
      return dict(page = 'studentform', form = StudentForm)
         
   @expose()
   def save_record(self, **kw):
      newstudent = student(name = kw['name'],city = kw['city'],
         address = kw['address'], pincode = kw['pincode'])
      DBSession.flush()
      flash(message = "new entry added successfully")
      redirect("/listrec")

I seguenti modelli vengono creati nella cartella dei modelli:

Ciao \ templates \ studentform.html

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:py = "http://genshi.edgewall.org/" lang = "en">
	
   <head>
      <title>Student Registration Form</title>
   </head>
	

   <body>
      <div id = "getting_started">
         ${form.display(value = dict(title = 'Enter data'))}
      </div>
   </body>
	
</html>

Ciao \ templates \ studentlist.html

<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:py = "http://genshi.edgewall.org/">

   <head>
      <link rel = "stylesheet" type = "text/css" media = "screen" 
         href = ${tg.url('/css/style.css')}" /> <title>Welcome to TurboGears</title> </head> <body> <h1>Welcome to TurboGears</h1> <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with> <h2>Current Entries</h2> <table border = '1'> <thead> <tr> <th>Name</th> <th>City</th> <th>Address</th> <th>Pincode</th> </tr> </thead> <tbody> <py:for each = "entry in entries"> <tr> <td>${entry.name}</td>
                  <td>${entry.city}</td> <td>${entry.address}</td>
                  <td>${entry.pincode}</td>
               </tr>
            </py:for>
         </tbody>
      </table>
		
   </body>
	
</html>

Riavvia il server ed entra http://localhost:8080/add nel browser -

Ogni volta che i dati vengono aggiunti e viene premuto il pulsante di invio, verrà visualizzato l'elenco delle voci correnti.

Il toolkit Gearbox contiene il comando scaffold, molto utile per creare rapidamente nuovi componenti dell'applicazione TurboGears. Un'applicazione generata dal comando di avvio rapido di gearbox ha un modello di scheletro nella cartella del modello (model.py.template), una cartella dei modelli (template.html.template) e una cartella dei controller (controller.py.template). Questi file ".template" vengono utilizzati come base per la creazione di nuovi scaffold per un'applicazione

Ad esempio, per creare un nuovo modello chiamato mymodel, esegui semplicemente il seguente comando:

gearbox scaffold model mymodel

Questo comando genererà model / mymodel.py con la classe newmodel definita al suo interno.

# -*- coding: utf-8 -*-
"""Mymodel model module."""
from sqlalchemy import *
from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode, DateTime, LargeBinary
from sqlalchemy.orm import relationship, backref
from hello.model import DeclarativeBase, metadata, DBSession

class Mymodel(DeclarativeBase):
   __tablename__ = 'mymodels'
   
   uid = Column(Integer, primary_key = True)
   data = Column(Unicode(255), nullable = False)
   
   user_id = Column(Integer, ForeignKey('tg_user.user_id'), index = True)
   user = relationship('User', uselist = False,
      backref = backref('mymodels',cascade = 'all, delete-orphan'))
   __all__ = ['Mymodel']

Gli utenti possono ora apportare modifiche alla struttura della tabella secondo le loro esigenze e quindi importarle all'interno model/__init__.py per rendere disponibile il modello all'interno dell'applicazione.

Per creare un modello, una classe controller per gestirlo e una pagina di indice tutti questi tre componenti possono essere creati simultaneamente dal seguente comando.

gearbox scaffold model controller template mymodel

Questo comando risulterà in controllers \ mymodel.py in cui la classe MymodelController è debitamente definita.

# -*- coding: utf-8 -*-
"""Mymodel controller module"""

from tg import expose, redirect, validate, flash, url
# from tg.i18n import ugettext as _
# from tg import predicates

from hello.lib.base import BaseController
# from hello.model import DBSession

class MymodelController(BaseController):
   # Uncomment this line if your controller requires an authenticated user
   # allow_only = predicates.not_anonymous()
   
   @expose('hello.templates.mymodel')
   def index(self, **kw):
      return dict(page = 'mymodel-index')

Per iniziare a utilizzare questo controller, montalo all'interno dell'applicazione RootController solo per definire un'istanza di MymodelController. Aggiungi queste righe in controller \ root.py -

From hello.controller.mymodel import MymodelController

class RootController(BaseController): mymodel = MymodelController()

Nella cartella dei modelli verrà anche creato un modello di scaffold templates \ mymodel.html. Agirà come una pagina di indice per l'URL "/ mymodel".

Il generato mymodel.html file nella cartella dei modelli sarà il seguente:

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   xmlns:xi = "http://www.w3.org/2001/XInclude">
	
   <xi:include href = "master.html" />
	
   <head>
      <title>Mymodel</title>
   </head>
	
   <body>
      <div class = "row">
         <div class = "col-md-12">
            <h2>Mymodel</h2>
            <p>Template page for Mymodel</p>
         </div>
      </div>
   </body>
	
</html>

Ci sono tre modi in TurboGears per collegare comportamenti all'interno delle applicazioni esistenti.

  • Hook - È un meccanismo mediante il quale è possibile definire un evento e notificare ai listener registrati come e quando gli eventi vengono emessi.

  • Controller Wrapper- Si trova tra TurboGears e Controller, in modo che sia possibile estendere il controller come un decoratore. Pertanto, può essere collegato a qualsiasi applicazione controller di terze parti.

  • Application Wrapper - È simile a qualsiasi middleware WSGI, ma funziona solo nel contesto TurboGears.

In questo capitolo, discuteremo come utilizzare gli hook all'interno di un'applicazione esistente.

Ganci

Gli hook sono eventi registrati nel file di configurazione dell'applicazione app_cfg.py. Qualsiasi controller viene quindi agganciato a questi eventi dai decoratori di eventi.

I seguenti hook sono definiti in TurboGears:

Sr.No. Ganci e descrizione
1

Startup()

solo a livello di applicazione, chiamato all'avvio dell'applicazione.

2

shutdown()

solo a livello di applicazione, chiamato quando l'applicazione esce.

3

configure_new_app

nuova applicazione è stata creata dal configuratore dell'applicazione.

4

before_config(app)

solo a livello di applicazione, chiamato subito dopo la creazione dell'applicazione, ma prima di impostare le opzioni e il middleware

5

after_config(app)

solo a livello di applicazione, chiamato dopo aver finito di impostare tutto.

6

before_validate

Chiamato prima di eseguire la convalida

7

before_call

Chiamato dopo la convalida, prima di chiamare il metodo del controller effettivo.

8

before_render

Chiamato prima del rendering di un modello di controller, output è il valore restituito dal controller.

9

after_render

Chiamato dopo aver terminato il rendering di un modello di controller.

Registra un Hook

In modo da register a Hook, creare funzioni in app_cfg.py e quindi registrarli utilizzando il codice seguente:

tg.hooks.register(hookane, function, controller)

Nel codice seguente, gli hook on_startup, on_shutdown e before_render sono registrati in app_cfg.py.

def on_startup():
   print 'hello, startup world'
   
def on_shutdown():
   print 'hello, shutdown world'
   
def before_render(remainder, params, output):
   print 'system wide before render'
   
# ... (base_config init code)
tg.hooks.register('startup', on_startup)
tg.hooks.register('shutdown', on_shutdown)
tg.hooks.register('before_render', before_render)

L'hook before_render è registrato con una funzione controller nel Rootcontroller. Aggiungi il codice seguente in controllers \ root.py.

from tg.decorators import before_render

class RootController(BaseController):
   @expose('hello.templates.index')
   @before_render(before_render_cb)
	
   def index(self, *args, **kw):
      return dict(page = 'index')

Quando l'applicazione è servita, il messaggio di avvio viene visualizzato nella console.

hello, startup world
Starting Standard HTTP server on http://127.0.0.1:8080

Quando l'URL "/" viene inserito nel browser, sulla console viene visualizzato un messaggio corrispondente all'hook before_render.

system wide before render
Going to render {'page': 'index'}

Le estensioni TurboGears sono identificate da tgext.* package. Un toolkit Gearbox fornisce il comando tgext per creare un'estensione di esempio. Ad esempio:

gearbox tgext -n myextension

Altri parametri opzionali per questo comando sono:

  • --author - nome dell'autore del pacchetto.

  • --email - email dell'autore del pacchetto.

  • --licence- licenza utilizzata per il pacchetto. L'impostazione predefinita è MIT.

  • --description - Descrizione del pacchetto.

  • --keywords - Parole chiave del pacchetto (predefinito: turbogears2.extension).

Questo creerà una directory tgext.myextension, che ha una semplice estensione di esempio all'interno.

Run the setup.py all'interno della directory -

Python setup.py install

Il _init_.py file all'interno tgext/myextension la cartella contiene -

  • Plugme function - Questo è il punto di ingresso dell'estensione.

  • SetupExtension class - qui avviene l'inizializzazione dell'estensione.

  • On_startup function - all'interno della classe c'è un hook registrato sulla funzione __call__ all'interno della classe.

Breve versione del tgext\myextension\__init__.py.

from tg import config
from tg import hooks
from tg.configuration import milestones

import logging
log = logging.getLogger('tgext.myextension')

def plugme(configurator, options = None):
   if options is None:
      options = {}
   log.info('Setting up tgext.myextension extension...')
   milestones.config_ready.register(SetupExtension(configurator))
   
   return dict(appid='tgext.myextension')
	
class SetupExtension(object):
   def __init__(self, configurator):
      self.configurator = configurator
      
   def __call__(self):
      log.info('>>> Public files path is %s' % config['paths']['static_files'])
      hooks.register('startup', self.on_startup)
      
   def echo_wrapper_factory(handler, config):
      def echo_wrapper(controller, environ, context):
         log.info('Serving: %s' % context.request.path)
         return handler(controller, environ, context)
      return echo_wrapper
      
   self.configurator.register_wrapper(echo_wrapper_factory)
   
   def on_startup(self):
      log.info('+ Application Running!')

Una volta installata l'estensione, attivala apportando le seguenti aggiunte nel file dell'applicazione app_cfg.py file di configurazione.

from tgext.myextension import plugme

plugme(base_config)

Se avviamo il server utilizzando un comando del server gearbox, la notifica di una nuova estensione registrata può essere visualizzata sulla console nel modo seguente:

14:29:13,250 INFO [tgext.myextension] Setting up tgext.myextension extension...
14:29:13,453 INFO [tgext.myextension] >>> Public files path is c:\tghello\hello\hello\public
14:29:13,453 INFO [tgext.myextension] + Application Running!

Starting Standard HTTP server on http://127.0.0.1:8080

Se la tua estensione deve esporre modelli e controller, probabilmente vorrai dare un'occhiata al file Pluggable Applications, che hanno lo scopo di creare applicazioni Turbogears riutilizzabili che possono essere inserite all'interno di altre applicazioni per estenderne le funzionalità.

Utilizzare il seguente comando del cambio per creare un'applicazione collegabile:

gearbox quickstart-pluggable plugtest

Queste applicazioni collegabili possono definire le proprie:

  • Controllers - che verrà montato automaticamente, quando l'applicazione viene eliminata.

  • Models - che sarà disponibile all'interno e all'esterno dell'applicazione collegata.

  • Helpers - che può essere automaticamente esposto nell'oggetto 'H' in un modello di applicazione.

  • Bootstrap - che verrà eseguito quando viene chiamata setup-app.

  • Statics - che sarà disponibile nel proprio percorso privato.

Installa questa applicazione plugtest e monta la stessa apportando le seguenti modifiche in app_cfg.py.

from tgext.pluggable import plug
plug(base_config, plugtest)

REST sta per REpresentazionale State Ttrasferimento. REST è un'architettura basata su standard web e utilizza il protocollo HTTP per la comunicazione dei dati. Ruota intorno a una risorsa in cui ogni componente è una risorsa e una risorsa è accessibile da un'interfaccia comune utilizzando metodi standard HTTP. REST è stato introdotto per la prima volta daRoy Fielding in 2000.

Cos'è un RestController

RestController in TurboGears fornisce un meccanismo per accedere al metodo della richiesta, non solo all'URL. La verbosità HTTP standard include: GET, POST, PUT e DELETE. Il RestController li supporta e aggiunge anche alcune scorciatoie per l'invio di URL che rendono la visualizzazione dei dati come moduli ed elenchi, un po 'più semplice per l'utente.

Per spiegare come funziona RESTful con TurboGears, definiremo un semplice servizio web che espone un elenco di studenti.

Il codice per il modello studente è fornito di seguito:

model \ student.py

# -* - coding: utf-8 -*-
from sqlalchemy import *

from sqlalchemy.orm import mapper, relation, relation, backref
from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode, DateTime
from hello.model import DeclarativeBase, metadata, DBSession
from datetime import datetime

class student(DeclarativeBase):
   __tablename__ = 'student'
   
   uid = Column(Integer, primary_key = True)
   name = Column(Unicode(20), nullable = False, default = '')
   city = Column(Unicode(20), nullable = False, default = '')
   address = Column(Unicode(100), nullable = False, default = '')
   pincode = Column(Unicode(10), nullable = False, default = '')

Ora crea un controller basato su RestController e fornisci una funzione di visualizzazione per elencare l'elenco degli studenti in formato json.

Controllers \ student.py

from tg import RestController
from tg import expose
from hello import model
from hello.model import DBSession
from hello.model.student import student
from tg.decorators import with_trailing_slash

class StudentController(RestController):
   @expose('json')
   def get_all(self):
      students = DBSession.query(student).all()
      return dict(students=students)

Montare questo StudentController in RootController dell'applicazione incorporando le seguenti righe in root.py -

from hello.controllers.student import StudentController

class RootController(BaseController):

   students = StudentController()

Andando a http://localhost:8080/students fornirà l'elenco dei nostri studenti codificati in formato json.

Usiamo il metodo post per definire come dobbiamo salvare il nostro studente nel database. Questo metodo viene chiamato ogni volta che il file http://localhost:8080/student si accede all'URL utilizzando una richiesta POST -

@expose('json')
def post(self, name, city, address, pincode):
   newstudent = student(name = name, city = city, address = address, pincode = pincode)
   DBSession.add(newstudent)
   DBSession.flush()
   return dict(student = newstudent)

Usando il get_one() metodo, possiamo visualizzare un elemento dal database all'utente -

@expose('json')
def get_one(self, movie_id):
   newstudent = DBSession.query(student).get(uid)
   return dict(movie = movie)

PUT è il metodo utilizzato per aggiornare un record esistente utilizzando REST -

@expose('json')
def put(self, name = name, city = city, address =  address, pincode = pincode, **kw):
   newstudent = DBSession.query(student).get(name)
   newstudent.name = name
   newstudent.city = city
   newstudent.address = address
   newstudent.pincode = pincode
   return dict(student = newstudent)

Il cavallo di battaglia dell'eliminazione è allegato al metodo post_delete. Qui rimuoviamo effettivamente il record dal database, quindi reindirizziamo alla pagina dell'elenco -

@expose('json')
def post_delete(self, uid, **kw):
   newstudent = DBSession.query(student).get(uid)
   DBSession.delete(newstudent)
   return dict(movie = newstudent.uid)

Per passare da un ambiente di sviluppo a un ambiente di produzione completo, l'applicazione deve essere distribuita su un server web reale. A seconda di ciò che hai, sono disponibili diverse opzioni per distribuire un'applicazione web TurboGears.

Apache con mod_wsgi

Il mod_wsgi è un modulo Apache sviluppato da Graham Dumpleton. Consente ai programmi WSGI di essere serviti utilizzando il server web Apache.

Innanzitutto, installa Apache 2.X per la tua piattaforma, se non lo hai già fatto. Una volta installato Apache, installa mod_wsgi. Crea e attiva l'ambiente virtuale Python sul server e installa TurboGears al suo interno.

Installa la tua applicazione all'interno del direttore dell'applicazione, quindi crea uno script denominato app.wsgi.

Configurare l'installazione di Apache come segue:

<VirtualHost *:80>
   ServerName www.site1.com
   WSGIProcessGroup www.site1.com
   WSGIDaemonProcess www.site1.com user = <username> 
      group = www-data threads = 4 python-path = <pythonpath>
   WSGIScriptAlias myapp/app.wsgi
	
   #Serve static files directly without TurboGears
   Alias /images
   Alias /css
   Alias /js
   CustomLog
   ErrorLog
</VirtualHost>

Riavvia Apache

genere http://www.site1.com/ su un browser per accedere all'applicazione.

TurboGears sotto Circus e Chaussette

Circus è un gestore di processi e socket. Può essere utilizzato per monitorare e controllare processi e prese. Se associato al server Chaussette WSGI, può diventare un potente strumento per distribuire la tua applicazione e gestire qualsiasi processo correlato richiesto dalle tue applicazioni.

TurboGears - GoogleAppEngine

Installa Google AppEngine SDK per Python dal seguente URL: https://cloud.google.coms

Installa Google AppEngine sul tuo sistema. Quindi apri la Console per gli sviluppatori di Google e accedi con il tuo account Google -https://console.developers.google.com/start

Crea un nuovo progetto chiamato mytgapp -

Utilizzando Google AppEngine Launcher, crea una nuova applicazione denominata mytgapp.

I seguenti file verranno creati nella directory specificata:

  • app.yaml
  • favicon.ico
  • index.yaml
  • main.py

Per impostazione predefinita, l'applicazione creata si basa sul framework Webapp2. Per rimuovere questa dipendenza, modifica il file app.yaml ed elimina la parte seguente:

libraries:
   - name: webapp2
   version: "2.5.2"

Crea un ambiente virtuale temporaneo in una directory denominata mytgapp e installa TurboGears. Crea un'applicazione TurboGears al suo interno. Ora possiamo procedere alla modifica del filemain.py file che viene avviato da AppEngine per eseguire la nostra applicazione e scrivere effettivamente un'applicazione TurboGears lì.

Aggiungi i seguenti contenuti in main.py -

import os
import site
site.addsitedir(os.path.join(os.path.dirname(__file__), 'packages'))
from tg import expose, TGController, AppConfig

class RootController(TGController):
   @expose()
   def index(self):
      return "<h1>Hello World</h1>"
		
config = AppConfig(minimal = True, root_controller = RootController())
app = config.make_wsgi_app()

Ora esegui l'applicazione da AppEngine Launcher e fai clic sul pulsante Sfoglia per vedere che l'applicazione funziona correttamente sull'host locale.

Abbiamo già creato un progetto denominato mytgapp nella console degli sviluppatori. Ora fai clic sul pulsante di distribuzione nel programma di avvio. Al termine del processo di distribuzione,http://mytgapp.appspot.com/ visita per visualizzare la nostra applicazione online.