Avvio rapido: Creare un'app API per Table con Python SDK e Azure Cosmos DB
SI APPLICA A: Tabella
Questo argomento di avvio rapido illustra come accedere all'API per Table di Azure Cosmos DB da un'applicazione Python. Azure Cosmos DB for Table è un archivio dati senza schema che consente alle applicazioni di archiviare dati NoSQL strutturati nel cloud. Poiché i dati vengono archiviati in una struttura senza schema, nuove proprietà (colonne) vengono automaticamente aggiunte alla tabella ogni volta che ad essa viene aggiunto un oggetto con un nuovo attributo. Le applicazioni Python possono accedere ad Azure Cosmos DB for Table usando il pacchetto Azure Data Tables SDK per Python.
Prerequisiti
L'applicazione di esempio viene scritta in Python 3.7 o versioni successive, anche se i principi si applicano a tutte le versioni dell'applicazione Python superiori a 3.7. È possibile usare Visual Studio Code come ambiente di sviluppo integrato.
Se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare.
Applicazione di esempio
L'applicazione di esempio per questa esercitazione può essere clonata o scaricata dal repository https://github.com/Azure-Samples/msdocs-azure-tables-sdk-python-flask.
git clone https://github.com/Azure-Samples/msdocs-azure-tables-sdk-python-flask.git
Nel repository di esempio sono incluse le cartelle di esempio 1-starter-app e 2-completed-app. La cartella 1-starter-app comprende alcune funzionalità da completare con righe contrassegnate da "#TODO". Si consiglia di completare la cartella 1-starter-app con i frammenti di codice illustrati in questo articolo.
L'applicazione di esempio completata usa dati meteo come esempio per illustrare le funzionalità dell'API per Table. Gli oggetti che rappresentano le osservazioni meteo vengono archiviati e recuperati usando l'API per Table; vengono archiviati anche oggetti con proprietà aggiuntive per illustrare le funzionalità senza schema dell'API per Table. L'immagine seguente mostra l'applicazione locale in esecuzione in un browser visualizzando i dati meteo archiviati in Azure Cosmos DB for Table.
1 - Creare un account Azure Cosmos DB
È prima necessario creare un account dell'API Table di Azure Cosmos DB che conterrà le tabelle usate nell'applicazione. Creare un account con il portale di Azure, l'interfaccia della riga di comando di Azure o Azure PowerShell.
Per creare un account Azure Cosmos DB, accedere al portale di Azure e seguire questa procedura.
2 - Creare una tabella
A questo punto, è necessario creare una tabella all'interno dell'account Azure Cosmos DB da usare per l'applicazione. A differenza di un database tradizionale, è necessario specificare solo il nome della tabella, non le proprietà (colonne) della tabella. Le proprietà (colonne) vengono create automaticamente nel momento in cui i dati vengono caricati nella tabella.
Nel portale di Azure completare i passaggi seguenti per creare una tabella all'interno dell'account Azure Cosmos DB.
3 - Ottenere la stringa di connessione di Azure Cosmos DB
Per accedere alle tabelle in Azure Cosmos DB, l'app richiede la stringa di connessione della tabella per l'account Cosmos DB Storage. La stringa di connessione può essere recuperata usando il portale di Azure, l'interfaccia della riga di comando di Azure o Azure PowerShell.
4 - Installare Azure Data Tables SDK per Python
Dopo aver creato un account Azure Cosmos DB, il passaggio successivo consiste nell'installare Microsoft Azure Data Tables SDK per Python. Per informazioni dettagliate sull'installazione dell'SDK, vedere il file README.rst nel repository relativo a Data Tables SDK for Python su GitHub.
Installare la libreria client di Azure Tables per Python con pip:
pip install azure-data-tables
Non dimenticare di installare anche il file requirements.txt nelle cartelle 1-starter-app o 2-completed-app.
5 - Configurare il client Table in un file con estensione env
Copiare la stringa di connessione dell'account Azure Cosmos DB dal portale di Azure e creare un oggetto TableServiceClient usando la stringa di connessione copiata. Passare alla cartella 1-starter-app o 2-completed-app. Indipendentemente dall'app da cui si inizia, è necessario definire le variabili di ambiente in un file .env
.
# Configuration Parameters
conn_str = "A connection string to an Azure Cosmos DB account."
table_name = "WeatherData"
project_root_path = "Project abs path"
Azure SDK comunica con Azure usando oggetti client per eseguire diverse operazioni in Azure. L'oggetto TableServiceClient
è l'oggetto usato per comunicare con Azure Cosmos DB for Table. Un'applicazione avrà in genere una sola classe TableServiceClient
complessiva e una classe TableClient
per ogni tabella.
Il codice seguente, ad esempio, crea un oggetto TableServiceClient
usando la stringa di connessione dalla variabile di ambiente.
self.conn_str = os.getenv("conn_str")
self.table_service = TableServiceClient.from_connection_string(self.conn_str)
6 - Implementare operazioni di tabella in Azure Cosmos DB
Tutte le operazioni di tabella di Azure Cosmos DB per l'app di esempio vengono implementate nella classe TableServiceHelper
che si trova nel file helper all'interno della directory webapp. È necessario importare la classe TableServiceClient
all'inizio di questo file per poter usare gli oggetti nella libreria client per Python azure.data.tables.
from azure.data.tables import TableServiceClient
All'inizio della classe TableServiceHelper
, creare un costruttore e aggiungere una variabile membro per l'oggetto TableClient
per consentire l'inserimento dell'oggetto TableClient
nella classe.
def __init__(self, table_name=None, conn_str=None):
self.table_name = table_name if table_name else os.getenv("table_name")
self.conn_str = conn_str if conn_str else os.getenv("conn_str")
self.table_service = TableServiceClient.from_connection_string(self.conn_str)
self.table_client = self.table_service.get_table_client(self.table_name)
Filtrare le righe restituite da una tabella
Per filtrare le righe restituite da una tabella, è possibile passare al metodo query_entities
una stringa di filtro dello stile OData. Ad esempio, se si desidera ottenere tutte le letture meteo per Chicago tra la mezzanotte del 1° luglio 2021 e la mezzanotte del 2 luglio 2021 (inclusi), passare la stringa di filtro seguente.
PartitionKey eq 'Chicago' and RowKey ge '2021-07-01 12:00 AM' and RowKey le '2021-07-02 12:00 AM'
È possibile visualizzare i relativi operatori di filtro OData nel sito Web azure-data-tables, nella sezione Scrittura filtri.
Quando il parametro request.args viene passato al metodo query_entity
nella classe TableServiceHelper
, crea una stringa di filtro per ogni valore di proprietà non nullo. Crea quindi una stringa di filtro combinata unendo tutti i valori insieme a una clausola “and". Questa stringa di filtro combinata viene passata al metodo query_entities
sull'oggetto TableClient
e vengono restituite solo le righe corrispondenti alla stringa di filtro. È possibile usare un metodo simile nel codice per costruire stringhe di filtro appropriate come richiesto dall'applicazione.
def query_entity(self, params):
filters = []
if params.get("partitionKey"):
filters.append("PartitionKey eq '{}'".format(params.get("partitionKey")))
if params.get("rowKeyDateStart") and params.get("rowKeyTimeStart"):
filters.append("RowKey ge '{} {}'".format(params.get("rowKeyDateStart"), params.get("rowKeyTimeStart")))
if params.get("rowKeyDateEnd") and params.get("rowKeyTimeEnd"):
filters.append("RowKey le '{} {}'".format(params.get("rowKeyDateEnd"), params.get("rowKeyTimeEnd")))
if params.get("minTemperature"):
filters.append("Temperature ge {}".format(params.get("minTemperature")))
if params.get("maxTemperature"):
filters.append("Temperature le {}".format(params.get("maxTemperature")))
if params.get("minPrecipitation"):
filters.append("Precipitation ge {}".format(params.get("minPrecipitation")))
if params.get("maxPrecipitation"):
filters.append("Precipitation le {}".format(params.get("maxPrecipitation")))
return list(self.table_client.query_entities(" and ".join(filters)))
Inserire dati usando un oggetto TableEntity
Il modo più semplice per aggiungere dati a una tabella è utilizzare un oggetto TableEntity
. In questo esempio i dati vengono mappati da un oggetto del modello di input a un oggetto TableEntity
. Le proprietà dell'oggetto di input che rappresentano il nome della stazione meteo e la data/ora di osservazione vengono mappate, rispettivamente, alle proprietà PartitionKey
e RowKey
, che insieme formano una chiave univoca per la riga della tabella. Le proprietà aggiuntive sull'oggetto del modello di input vengono quindi mappate alle proprietà del dizionario sull'oggetto TableEntity. Infine, il metodo create_entity
sull'oggetto TableClient
viene utilizzato per inserire dati nella tabella.
Modificare la funzione insert_entity
nell'applicazione di esempio in modo da contenere il codice seguente.
def insert_entity(self):
entity = self.deserialize()
return self.table_client.create_entity(entity)
@staticmethod
def deserialize():
params = {key: request.form.get(key) for key in request.form.keys()}
params["PartitionKey"] = params.pop("StationName")
params["RowKey"] = "{} {}".format(params.pop("ObservationDate"), params.pop("ObservationTime"))
return params
Eseguire l'upsert dei dati tramite un oggetto TableEntity
Se si tenta di inserire una riga in una tabella con una combinazione "chiave di partizione/chiave di riga" già esistente nella tabella, si riceverà un errore. Per questo motivo, è spesso preferibile usare il metodo upsert_entity
anziché il create_entity
quando si aggiungono righe a una tabella. Se la combinazione chiave di partizione/chiave di riga specificata esiste già nella tabella, il upsert_entity
metodo aggiorna la riga esistente. In caso contrario, la riga viene aggiunta alla tabella.
def upsert_entity(self):
entity = self.deserialize()
return self.table_client.upsert_entity(entity)
@staticmethod
def deserialize():
params = {key: request.form.get(key) for key in request.form.keys()}
params["PartitionKey"] = params.pop("StationName")
params["RowKey"] = "{} {}".format(params.pop("ObservationDate"), params.pop("ObservationTime"))
return params
Inserire o eseguire l'upsert dei dati con proprietà variabili
Uno dei vantaggi dell'utilizzo di Azure Cosmos DB for Table è che se un oggetto caricato in una tabella contiene nuove proprietà, tali proprietà vengono aggiunte automaticamente alla tabella e i valori archiviati in Azure Cosmos DB. Non è necessario eseguire istruzioni DDL come ALTER TABLE per aggiungere colonne come in un database tradizionale.
Questo modello offre flessibilità all'applicazione quando si gestiscono origini dati che possono aggiungere o modificare i dati da acquisire nel tempo o quando input diversi forniscono dati diversi all'applicazione. Nell'applicazione di esempio è possibile simulare una stazione meteo che invia non solo i dati meteo di base, ma anche alcuni valori aggiuntivi. Quando un oggetto con queste nuove proprietà viene archiviato nella tabella per la prima volta, le proprietà corrispondenti (colonne) vengono automaticamente aggiunte alla tabella.
Per inserire o eseguire l'upsert di un oggetto di questo tipo usando l'API per Table, eseguire il mapping delle proprietà dell'oggetto espandibile in un oggetto TableEntity
e utilizzare i metodi create_entity
o upsert_entity
sull'oggetto TableClient
secondo necessità.
Nell'applicazione di esempio, la funzione upsert_entity
può implementare anche la funzione di inserimento o di upsert dei dati con proprietà variabili
def insert_entity(self):
entity = self.deserialize()
return self.table_client.create_entity(entity)
def upsert_entity(self):
entity = self.deserialize()
return self.table_client.upsert_entity(entity)
@staticmethod
def deserialize():
params = {key: request.form.get(key) for key in request.form.keys()}
params["PartitionKey"] = params.pop("StationName")
params["RowKey"] = "{} {}".format(params.pop("ObservationDate"), params.pop("ObservationTime"))
return params
Aggiornare un'entità
Le entità possono essere aggiornate chiamando il metodo update_entity
sull'oggetto TableClient
.
Nell'app di esempio, questo oggetto viene passato al metodo upsert_entity
nella classe TableClient
. Aggiorna l'oggetto entità e usa il metodo upsert_entity
per salvare gli aggiornamenti nel database.
def update_entity(self):
entity = self.update_deserialize()
return self.table_client.update_entity(entity)
@staticmethod
def update_deserialize():
params = {key: request.form.get(key) for key in request.form.keys()}
params["PartitionKey"] = params.pop("StationName")
params["RowKey"] = params.pop("ObservationDate")
return params
Rimuovere un'entità
Per rimuovere un'entità da una tabella, chiamare il metodo delete_entity
sull'oggetto TableClient
con la chiave di partizione e la chiave di riga dell'oggetto.
def delete_entity(self):
partition_key = request.form.get("StationName")
row_key = request.form.get("ObservationDate")
return self.table_client.delete_entity(partition_key, row_key)
7 - Eseguire il codice
Eseguire l'applicazione di esempio per interagire con Azure Cosmos DB for Table. Ad esempio, a partire dalla cartella 2-completed-app, con i requisiti installati, è possibile usare:
python3 run.py webapp
Per altre informazioni sull'esecuzione dell'applicazione di esempio, vedere il file README.md all'interno della radice del repository di esempio.
La prima volta che si esegue l'applicazione, non saranno presenti dati perché la tabella è vuota. Usare uno qualsiasi dei pulsanti nella parte superiore dell'applicazione per aggiungere dati alla tabella.
Selezionando il pulsante Inserisci tramite entità tabella, si apre una finestra di dialogo che consente di inserire o eseguire l'upsert di una nuova riga utilizzando un oggetto TableEntity
.
Selezionando il pulsante Inserisci tramite dati espandibili viene visualizzata una finestra di dialogo che consente di inserire un oggetto con proprietà personalizzate, dimostrando come Azure Cosmos DB for Table aggiunga automaticamente proprietà (colonne) alla tabella quando necessario. Usare il pulsante Aggiungi campo personalizzato per aggiungere una o più nuove proprietà e dimostrare questa funzionalità.
Usare il pulsante Inserisci dati di esempio per caricare alcuni dati di esempio nella tabella di Azure Cosmos DB.
Per la cartella di esempio 1-starter-app, è necessario completare almeno il codice per la funzione
submit_transaction
per accertarsi che l'inserimento dei dati di esempio abbia esito positivo.I dati di esempio vengono caricati da un file sample_data.json. La variabile .env
project_root_path
indica all'app dove trovare il file. Se, ad esempio, si esegue l'applicazione dalla cartella 1-starter-app o 2-completed-app, impostareproject_root_path
su "" (vuoto).
Selezionare la voce Filtra i risultati nel menu in alto per aprire la pagina Filtra i risultati. In questa pagina compilare i criteri di filtro per illustrare come creare e passare una clausola di filtro ad Azure Cosmos DB for Table.
Pulire le risorse
Dopo aver finito di usare l'applicazione di esempio, è necessario rimuovere tutte le risorse di Azure correlate a questo articolo dall'account Azure. È possibile rimuovere tutte le risorse eliminando il gruppo di risorse.
È possibile eliminare un gruppo di risorse usando il portale di Azure e seguendo questa procedura.
Passaggi successivi
In questa guida di avvio rapido si è appreso come creare un account Azure Cosmos DB, come creare una tabella con Esplora dati e come eseguire un'app. È ora possibile eseguire query sui dati usando l'API per Table.