Table Storage¶
This recipe covers reading and writing entities in Azure Table Storage from Azure Functions Python v2 using the table input and output bindings. Table Storage is a low-cost, schemaless key/value store keyed by partition and row.
Architecture¶
flowchart TD
HTTP[HTTP Request] --> FA[Function App]
FA -->|table_output| WRITE[(Table: entity written)]
READ[(Table: entity read)] -->|table_input| FA Prerequisites¶
Table bindings ship in the default extension bundle. Provide the connection in app settings. A connection string or an identity-based connection is supported. Identity-based connections use a __tableServiceUri suffix:
az functionapp config appsettings set \
--name $APP_NAME \
--resource-group $RG \
--settings "TableConnection__tableServiceUri=https://$STORAGE_NAME.table.core.windows.net"
| CLI element | Explanation |
|---|---|
| Command(s) | az functionapp config appsettings set |
| Key flags | --name, --resource-group, --settings |
| Variables | $APP_NAME, $RG, $STORAGE_NAME |
| Expected result | Azure CLI returns the updated app settings as JSON; confirm the setting is present before continuing. |
For an identity-based connection, grant the managed identity Storage Table Data Reader (input) and Storage Table Data Contributor (output) on the storage account.
Output binding creates new entities only
The table output binding only creates new entities. To update or delete an existing entity, use the azure-data-tables SDK directly with a TableClient.
Output Binding: Write an Entity¶
Every entity requires a PartitionKey and a RowKey.
import azure.functions as func
import uuid
import json
bp = func.Blueprint()
@bp.route(route="messages", methods=["POST"])
@bp.table_output(
arg_name="entity",
connection="TableConnection",
table_name="messages",
)
def create_message(req: func.HttpRequest, entity: func.Out[str]) -> func.HttpResponse:
"""Persist a new message entity to Table Storage."""
body = req.get_json()
row_key = str(uuid.uuid4())
data = {
"PartitionKey": "message",
"RowKey": row_key,
"Text": body.get("text", ""),
}
entity.set(json.dumps(data))
return func.HttpResponse(
json.dumps({"rowKey": row_key}),
mimetype="application/json",
status_code=201,
)
Input Binding: Read an Entity¶
Bind by partition key and row key to read a single entity. The runtime injects the entity as a JSON string.
@bp.route(route="messages/{partitionKey}/{rowKey}", methods=["GET"])
@bp.table_input(
arg_name="entity",
connection="TableConnection",
table_name="messages",
partition_key="{partitionKey}",
row_key="{rowKey}",
)
def get_message(req: func.HttpRequest, entity: str) -> func.HttpResponse:
"""Read a single entity by partition and row key."""
return func.HttpResponse(
entity,
mimetype="application/json",
status_code=200,
)
To read multiple entities, omit row_key and optionally supply a filter and take on the input binding.