Criando seu primeiro aplicativo

Do princípio

Aplicativos podem ser criados usando o painel ou directamente a partir do sistema de arquivos. Aqui, nós estamos indo para fazê-lo manualmente, como o Dashboard é descrito em seu próprio capítulo.

Tenha em mente que um aplicativo é um módulo Python; portanto, precisa apenas de uma pasta e um `` __init arquivo __ py`` nessa pasta.:

mkdir apps/myapp
echo '' > apps/myapp/__init__.py

Dica

para Windows, você deve usar barras invertidas (ou seja, “\”) em vez de barras. Além disso, um vazio * __ o init __. Py * arquivo não é estritamente necessária desde Python 3.3, mas será útil mais tarde.

Se você agora reiniciar py4web ou pressione o botão “Atualizar Apps” no Dashboard, py4web vai encontrar este módulo, importá-lo e reconhecê-lo como um aplicativo, simplesmente por causa de sua localização. Um aplicativo não é obrigado a fazer nada. Poderia ser apenas um recipiente para arquivos estáticos ou código arbitrário que outros aplicativos pode querer importação e de acesso. No entanto, normalmente a maioria dos aplicativos são projetados para expor páginas estáticas ou dinâmicas.

Páginas estáticas

Para expor páginas estáticas você simplesmente precisa para criar um `` subpasta static`` e qualquer arquivo lá será automaticamente publicado:

mkdir apps/myapp/static
echo 'Hello World' > apps/myapp/static/hello.txt

O arquivo recém-criado será acessível em

http://localhost:8000/myapp/static/hello.txt

Note que `` static`` é um caminho especial para py4web e arquivos somente sob o `` static`` pasta são servidos.

Importante: py4web internamente usa a garrafa static_file <https://bottlepy.org/docs/dev/tutorial.html#static-files> __ método para servir arquivos estáticos, o que significa que suporta streaming, conteúdo parcial, pedidos de intervalo, e If-Modified-Since. Isso tudo é feito automaticamente com base nos cabeçalhos de solicitação HTTP.

Páginas web dinâmicas

Para criar uma página dinâmica, você deve criar uma função que retorna o conteúdo da página. . Por exemplo editar a `` novaaplicacao / __ __ Init py`` como se segue:

import datetime
from py4web import action

@action('index')
def page():
    return "hello, now is %s" % datetime.datetime.now()

Py4web Restart ou pressione o botão “Atualizar Apps” botão do painel, e esta página será acessível em

http://localhost:8000/myapp/index

ou

http://localhost:8000/myapp

(Note que o índice é opcional)

Ao contrário de outras estruturas, nós não importar ou iniciar o servidor web dentro do `` código myapp``. Isso ocorre porque py4web já está em execução, e pode servir vários aplicativos. py4web importa nossas funções de código e expõe decorados com `` @Action () . Note também que prepends py4web `` / myapp (ou seja, o nome do aplicativo) para o caminho url declarado na ação. Isso ocorre porque existem vários aplicativos, e eles podem definir rotas conflitantes. Antecedendo o nome do aplicativo remove a ambiguidade. Mas há uma exceção: se você chamar seu aplicativo `` _default``, ou se você criar um link simbólico do `` _default`` para `` myapp``, então py4web não irá anteceder qualquer prefixo para as rotas definidas dentro do aplicativo .

Em valores de retorno

ações py4web deve retornar uma string ou um dicionário. Se eles retornar um dicionário que você deve dizer py4web o que fazer com ele. Por padrão py4web serializará-lo em JSON. Por exemplo editar `` __init __. Py`` novamente e adicionar

@action('colors')
def colors():
    return {'colors': ['red', 'blue', 'green']}

Esta página será visível na

http://localhost:8000/myapp/colors

e retorna um objeto JSON `` { «cores»: [ «vermelho», «azul», «verde»]} ``. Observe que escolhemos nomear a função o mesmo que a rota. Isso não é necessário, mas é uma convenção que muitas vezes se seguirão.

Você pode usar qualquer linguagem de modelo para transformar seus dados em uma string. PY4WEB vem com yatl, um capítulo inteiro será dedicado mais tarde e iremos fornecer um exemplo em breve.

Rotas

É possível mapear padrões do URL em argumentos da função. Por exemplo:

@action('color/<name>')
def color(name):
    if name in ['red', 'blue', 'green']:
        return 'You picked color %s' % name
    return 'Unknown color %s' % name

Esta página será visível na

http://localhost:8000/myapp/color/red

A sintaxe dos padrões é o mesmo que os rotas Garrafa <https://bottlepy.org/docs/dev/tutorial.html#request-routing> __. Uma rota WildCard pode ser definida como

  • `` <Name> `` ou

  • `` <Name: filter> `` ou

  • `` ` ` `

E estes são possíveis filtros (somente ` `: `tem uma config):

  • : Resultados int dígitos (assinatura) e converte o valor de número inteiro.

  • : Float semelhante a: int mas para números decimais.

  • : Path corresponde a todos os personagens, incluindo o caractere de barra de uma forma não-ganancioso, e pode ser usado para combinar mais de um segmento de caminho.

  • ``: Re [: exp] `` `permite especificar uma expressão regular personalizado no campo de configuração. O valor combinado não é modificado.

O padrão de harmonização o carácter universal é passado para a função sob a variável especificada `` name``.

Além disso, o decorador acção tem um argumento `` method`` opcional que pode ser um método HTTP ou uma lista de métodos:

@action('index', method=['GET','POST','DELETE'])

Você pode usar vários decoradores para expor a mesma função em várias rotas.

O objeto `` request``

De py4web você pode importar `` request``

from py4web import request

@action('paint')
def paint():
    if 'color' in request.query
       return 'Painting in %s' % request.query.get('color')
    return 'You did not specify a color'

Esta ação pode ser acessado em:

http://localhost:8000/myapp/paint?color=red

Observe que o objeto de solicitação é um pedido objeto Garrafa <https://bottlepy.org/docs/dev/api.html#the-request-object> _.

Modelos

Para utilizar um yatl modelo que você deve declará-lo. Por exemplo, criar um arquivo `` apps / myapp / templates / paint.html`` que contém:

<html>
 <head>
    <style>
      body {background:[[=color]]}
    </style>
 </head>
 <body>
    <h1>Color [[=color]]</h1>
 </body>
</html>

em seguida, modificar a ação de tinta para usar o modelo e padrão para verde.

@action('paint')
@action.uses('paint.html')
def paint():
    return dict(color = request.query.get('color', 'green'))

A página irá agora mostrar o nome da cor em um fundo da cor correspondente.

O ingrediente chave aqui é o decorador `` @ action.uses (…) . Os argumentos de `` action.uses são chamados luminárias ** **. Você pode especificar vários dispositivos elétricos em um decorador ou você pode ter vários decoradores. Chaves são objectos que modificam o comportamento da acção, que podem precisar de ser inicializado por pedido, que podem realizar uma filtragem de entrada e de saída da acção, e que pode depender de cada-outro (eles são semelhantes no seu âmbito à garrafa encaixes, mas eles são declarados por ação, e eles têm uma árvore de dependência que será explicado mais tarde).

O tipo mais simples de acessório é um modelo. Você especifica que simplesmente dando o nome do arquivo a ser usado como modelo. Esse arquivo deve seguir a sintaxe yatl e deve estar localizado no diretório `` templates`` pasta do aplicativo. O objeto retornado pela ação serão processados ​​pelo modelo e se transformou em uma corda.

Você pode facilmente definir luminárias para outras linguagens de modelo. Isto é descrito mais tarde.

Alguns built-in luminárias são:

  • o objeto DAL (que diz py4web para obter uma conexão de banco de dados a partir da piscina a cada pedido, e comprometer-se em caso de sucesso ou reversão em caso de falha)

  • o objeto de sessão (que diz py4web para analisar o cookie e recuperar uma sessão a cada pedido, e para salvá-lo, se alterado)

  • o objeto Tradutor (que diz py4web para processar o cabeçalho Accept-Language e determinar óptima internacionalização / pluralização regras)

  • o objeto Auth (que diz py4web que as necessidades de aplicativos acessar às informações do usuário)

Eles podem depender um do outro. Por exemplo, a sessão pode precisar a DAL (ligação de base de dados), e Auth podem precisamos de ambos. As dependências são tratados automaticamente.

De _scaffold

Na maioria das vezes, você não quer começar a escrever código a partir do zero. Você também quer seguir algumas convenções sãs descritas aqui, como não colocar todo seu código em `` __init __. Py``. PY4WEB fornece um aplicativo de Andaimes (_scaffold), onde os arquivos são organizados de forma adequada e muitos objetos úteis são pré-definidos.

Normalmente você vai encontrar o aplicativo andaime sob apps, mas você pode facilmente criar um novo clone de la manualmente ou usando o Dashboard.

Aqui está a estrutura da árvore do `` aplicativo _scaffold``:

├── __init__.py          # imports everything else
├── common.py            # defines useful objects
├── controllers.py       # your actions
├── databases            # your sqlite databases and metadata
    │   └── README.md
├── models.py            # your pyDAL table model
├── settings.py          # any settings used by the app
├── settings_private.py  # (optional) settings that you want to keep private
├── static               # static files
│   ├── README.md
│   ├── components       # py4web's vue auth component
│   │   ├── auth.html
│   │   └── auth.js
│   ├── css              # CSS files, we ship bulma because it is JS agnostic
│   │   └── no.css       # we used bulma.css in the past
│   ├── favicon.ico
│   └── js               # JS files, we ship with these but you can replace them
│       ├── axios.min.js
│       ├── sugar.min.js
│       ├── utils.js
│       └── vue.min.js
├── tasks.py
├── templates            # your templates go here
│   ├── README.md
│   ├── auth.html        # the auth page for register/logic/etc (uses vue)
│   ├── generic.html     # a general purpose template
│   ├── index.html
│   └── layout.html      # a bulma layout example
└── translations         # internationalization/pluralization files go here
    └── it.json          # py4web internationalization/pluralization files are in JSON, this is an italian example

O aplicativo andaime contém um exemplo de uma ação mais complexa:

from py4web import action, request, response, abort, redirect, URL
from yatl.helpers import A
from . common import db, session, T, cache, auth


@action('welcome', method='GET')
@action.uses('generic.html', session, db, T, auth.user)
def index():
    user = auth.get_user()
    message = T('Hello {first_name}'.format(**user))
    return dict(message=message, user=user)

Observe o seguinte:

  • `` `` Request``, response``, `` abort`` são definidos por garrafa

  • `` `` Redirect`` e URL`` são semelhantes aos seus homólogos web2py

  • ajudantes ( `` A``, `` div``, `` SPAN``, `` IMG``, etc.) deve ser importado a partir `` yatl.helpers``. Eles trabalham muito bem como em web2py

  • `` Db``, `` session``, `` T``, `` cache``, `` auth`` são Chaves. Eles devem ser definidos em `` common.py``.

  • `` @ Action.uses (auth.user) `` indica que esta acção espera um válido logado recuperáveis ​​usuário por `` auth.get_user () . Se isso não for o caso, esta ação redireciona para a página de login (definido também em `` common.py e usando o componente auth.html Vue.js).

Quando você começar a partir de andaime, você pode querer editar `` settings.py``, `` templates``, `` models.py`` e `` controllers.py`` mas provavelmente você não precisa mudar nada no `` common.py``.

Em seu HTML, você pode usar qualquer biblioteca JS que você quer, porque py4web é agnóstica para a sua escolha de JS e CSS, mas com algumas exceções. O `` auth.html`` que lida com registro / login / etc. usa um componente vue.js. Portanto, se você quiser usar isso, você não deve removê-lo.

App Watchdog

Py4web facilita a configuração de um servidor de desenvolvimento que recarrega automaticamente um aplicativo quando sua fonte Python arquivos mudança. Quaisquer outros arquivos dentro de um aplicativo pode ser visto através da criação de uma função de manipulador usando ** `` @ app_watch_handler`` decorador **.

--watch [off|sync|lazy]       Watch python changes and reload apps
                               automatically, modes: off (default), sync,
                               lazy

Dois exemplos de seu uso são relatados agora. Não se preocupe se você não undestand-los totalmente: o ponto-chave aqui é que mesmo código não-python pode ser recarregado automaticamente se explícita-lo com o ** `` @ app_watch_handler`` ** decorador.

Assista SASS arquivos e compilá-los quando editado:

from py4web.core import app_watch_handler
import sass # https://github.com/sass/libsass-python

@app_watch_handler(
    ["static_dev/sass/all.sass",
     "static_dev/sass/main.sass",
     "static_dev/sass/overrides.sass"])
def sass_compile(changed_files):
    print(changed_files) # for info, files that changed, from a list of watched files above
    ## ...
    compiled_css = sass.compile(filename=filep, include_paths=includes, output_style="compressed")
    dest = os.path.join(app, "static/css/all.css")
    with open(dest, "w") as file:
        file.write(compiled)

Validar sintaxe javascript quando editado:

import esprima # Python implementation of Esprima from Node.js

@app_watch_handler(
    ["static/js/index.js",
     "static/js/utils.js",
     "static/js/dbadmin.js"])
def validate_js(changed_files):
    for cf in changed_files:
        print("JS syntax validation: ", cf)
        with open(os.path.abspath(cf)) as code:
            esprima.parseModule(code.read())

Filepaths passado para ** `` @ app_watch_handler`` decorador ** deve ser relativo a um aplicativo. arquivos Python (ou seja, «*. py») em uma lista passada para o decorador são ignorados uma vez que eles são vigiados por padrão. parâmetro da função de manipulador é uma lista de caminhos de arquivos que foram alterados. Todas as exceções dentro manipuladores são impressos em terminal.