A RESTAPI¶
Desde a versão 19.5.10 PyDAL inclui uma API RESTful chamado RestAPI. É inspirado por GraphQL mas não é bem a mesma coisa, porque é menos poderoso, mas, no espírito do web2py, mais prático e mais fácil de usar. Como GraphSQL RestAPI permite que um cliente para consulta de informações usando o método GET e permite especificar alguns detalhes sobre o formato da resposta (que referências a seguir, e como desnormalizar os dados). Ao contrário GraphSQL ele permite que o servidor para especificar uma política e restringir quais consultas são permitidas e quais não são. Eles podem ser avaliados de forma dinâmica por solicitação com base no usuário e o estado do servidor. Como o nome implica RestAPI permite que todos os métodos stardard GET, POST, PUT e DELETE. Cada um deles pode ser ativado ou desativado com base na política, para tabelas individuais e campos individuais.
Nos exemplos abaixo assumimos um aplicativo chamado “super-heróis” e o seguinte modelo:
db.define_table(
'person',
Field('name'),
Field('job'))
db.define_table(
'superhero',
Field('name'),
Field('real_identity', 'reference person'))
db.define_table(
'superpower',
Field('description'))
db.define_table(
'tag',
Field('superhero', 'reference superhero'),
Field('superpower', 'reference superpower'),
Field('strength', 'integer'))
Também assumimos o seguinte controlador `` rest.py``:
from pydal.dbapi import RestAPI, Policy
policy = Policy()
policy.set('superhero', 'GET', authorize=True, allowed_patterns=['*'])
policy.set('*', 'GET', authorize=True, allowed_patterns=['*'])
# for security reasons we disabled here all methods but GET at the policy level, to enable any of them just set authorize = True
policy.set('*', 'PUT', authorize=False)
policy.set('*', 'POST', authorize=False)
policy.set('*', 'DELETE', authorize=False)
@action('api/<tablename>/', method = ['GET', 'POST'])
@action('api/<tablename>/<rec_id>', method = ['GET', 'PUT', 'DELETE'])
def api(tablename, rec_id=None):
return RestAPI(db, policy)(request.method,
tablename,
rec_id,
request.GET,
request.POST
)
A política é por tabela (ou * para todas as tabelas e por método. Autorizar pode ser verdade (permitir), False (negar) ou uma função com a assinatura (método, tablename, record_id, get_vars, post_vars) que retorna Verdadeiro / Falso . para a política GET pode especificar uma lista de padrões de consulta permitidos (* para todos). um padrão de consulta será comparado com as chaves na cadeia de consulta.
A acção acima referida é exposto como:
/superheroes/rest/api/{tablename}
** Sobre request.POST **: Manter em mente que ** ** request.POST contém apenas os dados do formulário que é publicado utilizando um formulário HTML normal ** ** ou javascript ** FormData ** objeto. Se você postar apenas objeto simples (por exemplo, `` axios.post ( “path / to / api”, {campo: “alguns”}) ``) você deve passar request.json ** ** em vez de request.POST, desde Este último irá conter request-corpo apenas cru que é corda, não json. Consulte a documentação bottle.py para mais detalhes.
RestAPI GET¶
A consulta geral tem a forma `` {} algo .eq = value`` onde `` eq = `` significa “igual”, `` gt = `` significa “maior que”, etc. A expressão pode ser prefixado por `` not.``.
`` {Algo} `` pode ser o nome de um campo na tabela foi consultado como em:
** Todos os super-heróis chamado de “Superman” **
/superheroes/rest/api/superhero?name.eq=Superman
Pode ser um nome de um campo de uma tabela referida pela tabela foi consultado como em:
** Todos os super-heróis com a identidade real “Clark Kent” **
/superheroes/rest/api/superhero?real_identity.name.eq=Clark Kent
Pode ser o nome de um campo de uma tabela que se refere ao neen tabela consultada como em:
** Todos os super-heróis com qualquer superpotência tag com força> 90 **
/superheroes/rest/api/superhero?superhero.tag.strength.gt=90
(Aqui tag é o nome da tabela de ligação, o anterior `` superhero`` é o nome do campo que faz referência ao quadro seleccionado e `` strength`` é o nome do campo utilizado para filtro)
Ele também pode ser um campo da tabela referenciada por uma tabela de muitos-para-muitos ligado como em:
** Todos os super-heróis com o poder de vôo **
/superheroes/rest/api/superhero?superhero.tag.superpower.description.eq=Flight
A chave para entender a sintaxe acima é para quebrá-lo da seguinte forma:
superhero?superhero.tag.superpower.description.eq=Flight
e lê-lo como:
selecionar registros da tabela ** super-herói ** referido pelo campo ** super-herói ** da tabela ** tag ** quando a superpotência ** ** campo dos ditos pontos de mesa para um recorde com a descrição ** ** ** ** eq ual para “Flight”.
A consulta permite modificadores adicionais, por exemplo
@offset=10
@limit=10
@order=name
@model=true
@lookup=real_identity
Os 3 primeiros são óbvias. @model retorna uma descrição JSON do modelo de banco de dados. Lookup desnormaliza o campo vinculado.
Aqui estão alguns exemplos práticos:
URL:
/superheroes/rest/api/superhero
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"id": 1
},
{
"real_identity": 2,
"name": "Spiderman",
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.132635",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?@model=true
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"id": 1
},
{
"real_identity": 2,
"name": "Spiderman",
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.098292",
"model": [
{
"regex": "[1-9]\\d*",
"name": "id",
"default": null,
"required": false,
"label": "Id",
"post_writable": true,
"referenced_by": [],
"unique": false,
"type": "id",
"options": null,
"put_writable": true
},
{
"regex": null,
"name": "name",
"default": null,
"required": false,
"label": "Name",
"post_writable": true,
"unique": false,
"type": "string",
"options": null,
"put_writable": true
},
{
"regex": null,
"name": "real_identity",
"default": null,
"required": false,
"label": "Real Identity",
"post_writable": true,
"references": "person",
"unique": false,
"type": "reference",
"options": null,
"put_writable": true
}
],
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?@lookup=real_identity
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": {
"name": "Clark Kent",
"job": "Journalist",
"id": 1
},
"name": "Superman",
"id": 1
},
{
"real_identity": {
"name": "Peter Park",
"job": "Photographer",
"id": 2
},
"name": "Spiderman",
"id": 2
},
{
"real_identity": {
"name": "Bruce Wayne",
"job": "CEO",
"id": 3
},
"name": "Batman",
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.178974",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?@lookup=identity:real_identity
(Desnormalizar o real_identity e renomeá-lo de identidade)
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"id": 1,
"identity": {
"name": "Clark Kent",
"job": "Journalist",
"id": 1
}
},
{
"real_identity": 2,
"name": "Spiderman",
"id": 2,
"identity": {
"name": "Peter Park",
"job": "Photographer",
"id": 2
}
},
{
"real_identity": 3,
"name": "Batman",
"id": 3,
"identity": {
"name": "Bruce Wayne",
"job": "CEO",
"id": 3
}
}
],
"timestamp": "2019-05-19T05:38:00.123218",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?@lookup=identity!:real_identity[name,job]
(Desnormalizar o real_identity [mas apenas campos nome e trabalho], recolher a com o prefixo de identidade)
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"name": "Superman",
"identity_job": "Journalist",
"identity_name": "Clark Kent",
"id": 1
},
{
"name": "Spiderman",
"identity_job": "Photographer",
"identity_name": "Peter Park",
"id": 2
},
{
"name": "Batman",
"identity_job": "CEO",
"identity_name": "Bruce Wayne",
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.192180",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?@lookup=superhero.tag
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"superhero.tag": [
{
"strength": 100,
"superhero": 1,
"id": 1,
"superpower": 1
},
{
"strength": 100,
"superhero": 1,
"id": 2,
"superpower": 2
},
{
"strength": 100,
"superhero": 1,
"id": 3,
"superpower": 3
},
{
"strength": 100,
"superhero": 1,
"id": 4,
"superpower": 4
}
],
"id": 1
},
{
"real_identity": 2,
"name": "Spiderman",
"superhero.tag": [
{
"strength": 50,
"superhero": 2,
"id": 5,
"superpower": 2
},
{
"strength": 75,
"superhero": 2,
"id": 6,
"superpower": 3
},
{
"strength": 10,
"superhero": 2,
"id": 7,
"superpower": 4
}
],
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"superhero.tag": [
{
"strength": 80,
"superhero": 3,
"id": 8,
"superpower": 2
},
{
"strength": 20,
"superhero": 3,
"id": 9,
"superpower": 3
},
{
"strength": 70,
"superhero": 3,
"id": 10,
"superpower": 4
}
],
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.201988",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?@lookup=superhero.tag.superpower
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"superhero.tag.superpower": [
{
"strength": 100,
"superhero": 1,
"id": 1,
"superpower": {
"id": 1,
"description": "Flight"
}
},
{
"strength": 100,
"superhero": 1,
"id": 2,
"superpower": {
"id": 2,
"description": "Strength"
}
},
{
"strength": 100,
"superhero": 1,
"id": 3,
"superpower": {
"id": 3,
"description": "Speed"
}
},
{
"strength": 100,
"superhero": 1,
"id": 4,
"superpower": {
"id": 4,
"description": "Durability"
}
}
],
"id": 1
},
{
"real_identity": 2,
"name": "Spiderman",
"superhero.tag.superpower": [
{
"strength": 50,
"superhero": 2,
"id": 5,
"superpower": {
"id": 2,
"description": "Strength"
}
},
{
"strength": 75,
"superhero": 2,
"id": 6,
"superpower": {
"id": 3,
"description": "Speed"
}
},
{
"strength": 10,
"superhero": 2,
"id": 7,
"superpower": {
"id": 4,
"description": "Durability"
}
}
],
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"superhero.tag.superpower": [
{
"strength": 80,
"superhero": 3,
"id": 8,
"superpower": {
"id": 2,
"description": "Strength"
}
},
{
"strength": 20,
"superhero": 3,
"id": 9,
"superpower": {
"id": 3,
"description": "Speed"
}
},
{
"strength": 70,
"superhero": 3,
"id": 10,
"superpower": {
"id": 4,
"description": "Durability"
}
}
],
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.322494",
"api_version": "0.1"
}
URL (que é uma linha única, dividida para facilitar a leitura):
/superheroes/rest/api/superhero?
@lookup=powers:superhero.tag[strength].superpower[description]
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"powers": [
{
"strength": 100,
"superpower": {
"description": "Flight"
}
},
{
"strength": 100,
"superpower": {
"description": "Strength"
}
},
{
"strength": 100,
"superpower": {
"description": "Speed"
}
},
{
"strength": 100,
"superpower": {
"description": "Durability"
}
}
],
"id": 1
},
{
"real_identity": 2,
"name": "Spiderman",
"powers": [
{
"strength": 50,
"superpower": {
"description": "Strength"
}
},
{
"strength": 75,
"superpower": {
"description": "Speed"
}
},
{
"strength": 10,
"superpower": {
"description": "Durability"
}
}
],
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"powers": [
{
"strength": 80,
"superpower": {
"description": "Strength"
}
},
{
"strength": 20,
"superpower": {
"description": "Speed"
}
},
{
"strength": 70,
"superpower": {
"description": "Durability"
}
}
],
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.309903",
"api_version": "0.1"
}
URL (que é uma linha única, dividida para facilitar a leitura):
/superheroes/rest/api/superhero?
@lookup=powers!:superhero.tag[strength].superpower[description]
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"powers": [
{
"strength": 100,
"description": "Flight"
},
{
"strength": 100,
"description": "Strength"
},
{
"strength": 100,
"description": "Speed"
},
{
"strength": 100,
"description": "Durability"
}
],
"id": 1
},
{
"real_identity": 2,
"name": "Spiderman",
"powers": [
{
"strength": 50,
"description": "Strength"
},
{
"strength": 75,
"description": "Speed"
},
{
"strength": 10,
"description": "Durability"
}
],
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"powers": [
{
"strength": 80,
"description": "Strength"
},
{
"strength": 20,
"description": "Speed"
},
{
"strength": 70,
"description": "Durability"
}
],
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.355181",
"api_version": "0.1"
}
URL (que é uma linha única, dividida para facilitar a leitura):
/superheroes/rest/api/superhero?
@lookup=powers!:superhero.tag[strength].superpower[description],
identity!:real_identity[name]
RESULTADO:
{
"count": 3,
"status": "success",
"code": 200,
"items": [
{
"name": "Superman",
"identity_name": "Clark Kent",
"powers": [
{
"strength": 100,
"description": "Flight"
},
{
"strength": 100,
"description": "Strength"
},
{
"strength": 100,
"description": "Speed"
},
{
"strength": 100,
"description": "Durability"
}
],
"id": 1
},
{
"name": "Spiderman",
"identity_name": "Peter Park",
"powers": [
{
"strength": 50,
"description": "Strength"
},
{
"strength": 75,
"description": "Speed"
},
{
"strength": 10,
"description": "Durability"
}
],
"id": 2
},
{
"name": "Batman",
"identity_name": "Bruce Wayne",
"powers": [
{
"strength": 80,
"description": "Strength"
},
{
"strength": 20,
"description": "Speed"
},
{
"strength": 70,
"description": "Durability"
}
],
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.396583",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?name.eq=Superman
RESULTADO:
{
"count": 1,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"id": 1
}
],
"timestamp": "2019-05-19T05:38:00.405515",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?real_identity.name.eq=Clark Kent
RESULTADO:
{
"count": 1,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"id": 1
}
],
"timestamp": "2019-05-19T05:38:00.366288",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?not.real_identity.name.eq=Clark Kent
RESULTADO:
{
"count": 2,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 2,
"name": "Spiderman",
"id": 2
},
{
"real_identity": 3,
"name": "Batman",
"id": 3
}
],
"timestamp": "2019-05-19T05:38:00.451907",
"api_version": "0.1"
}
URL:
/superheroes/rest/api/superhero?superhero.tag.superpower.description=Flight
RESULTADO:
{
"count": 1,
"status": "success",
"code": 200,
"items": [
{
"real_identity": 1,
"name": "Superman",
"id": 1
}
],
"timestamp": "2019-05-19T05:38:00.453020",
"api_version": "0.1"
}
Note todas resposta RestAPI ter os campos
{
"api_version": ...
"timestamp": ...
"status": ...
"code": ...
}
e alguns campos opcionais:
{
"count": ... (total matching, not total returned, for GET)
"items": ... (in response to a GET)
"errors": ... (usually validation error0
"models": ... (usually if status != success)
"message": ... (is if error)
}
As especificações exatas estão sujeitos a mudança uma vez que este é um novo recurso.