Libreria Python Consultazione DB GAzie
Client Python per consultare (e aggiornare) il DB GAzie tramite php-crud-api.
Questa pagina è la guida d'uso completa.
Installazione
pip install py_gazie
Uso rapido
from py_gazie import GazieClient
with GazieClient("http://127.0.0.1:8082/modules/api/index.php", "test-token",
timeout=15, default_company="001") as client:
product = client.get_table("product") # alias -> ProductTable (gaz_001artico)
resp = product.page(limit=5).search() # chaining: prima i filtri/pagina, poi search()
if resp.success: # controlla SEMPRE success
for rec in resp.data.records: # NavigableRecord: attributi, non .get()
print(rec.codice, "-", rec.descri)
print("totale:", resp.data.pagination.total_records)
else:
print("errore:", resp.status_code, resp.error)
Le tabelle: cosa passare a get_table()
| Vuoi | Passa | Ricevi | Sul wire |
|---|---|---|---|
| clienti | "customer" |
CustomerTable |
gaz_{company}clfoco |
| articoli | "product" |
ProductTable |
gaz_{company}artico |
| anagrafiche fiscali | "anagra" |
AnagraTable |
gaz_anagra |
| aziende | "company" |
CompanyTable |
gaz_aziend |
| documenti di fatturazione (testata) | "document" |
DocumentTable |
gaz_{company}tesdoc |
| altre tabelle | nome reale, es. "gaz_001catmer" |
GazieTable generica |
stesso nome |
- Solo gli alias attivano i metodi di dominio (
insert_record,get_by_code,search_by_description,get_rows,get_customer…): il nome reale dà sempre la tabella generica. - Tabella inesistente (o
companynon presente sul server) →ValueErrorcon il nome della tabella mancante. - Le tabelle sono cachate: stessa
company+nome → stessa istanza. Lacompanyesplicita vince sudefault_company; entrambe sono normalizzate a 3 cifre (2→'002').
Classe GazieTable — operazioni
Tutte le tabelle (alias e generiche) hanno lo stesso nucleo: create · update · delete · get_by_id · search ·
first · count · exists · add_filter · order_by. Schema del chaining:
t = client.get_table("customer")
t.and_filter("codice", "sw", "103") # AND (ripeti per aggiungere)
t.or_filter("descri", "cs", "Fermi") # OR (filter1/filter2)
t.add_filter("or", "descri,cs,Fermi") # stessa cosa da stringa 'campo,op,valore'
t.page(1, 10).order_by("codice,desc") # pagina + ordinamento (order_by = alias di order)
resp = t.search() # -> ApiResponse
resp = t.read() # lista | t.read(item_id) -> record singolo
resp = t.get_by_id(42) # UN record per chiave primaria -> ApiResponse
resp = t.first() # primo record o None
n = t.count() # totale filtrato (misurato:14 su artico)
ok = t.exists() # almeno uno?
resp = t.create({...}) / t.update(id, {...}) / t.delete(id)
⚠️ I filtri si accumulano sull'istanza e vengono azzerati solo quando leggi: mai lasciare filtri
appesi senza chiamare search()/read().
Operatori di filtro (misurati sul server, 22/09/2026)
- ✅
eq,neq,gt,sw(inizia per),cs(contiene),in(valori separati da,) - ❌
lkviene ignorato dal server (restituisce tutto): usacs - AND =
filterripetuto · OR =filter1/filter2· misto = intersezione - niente virgole nei valori: il filtro è la stringa
"campo,op,valore"
Formato della risposta
Ogni operazione ritorna un ApiResponse con quattro campi: success, status_code,
data, error.
| Cosa manda il server | Come si legge in data |
|---|---|
elenco {"records": [...], "results": N} |
PaginatedData: resp.data.records (lista), len(resp.data), resp.data.pagination.total_records |
| record singolo | dict grezzo: resp.data["codice"] |
errore (es. 404, code 1003) |
success=False, error="Record … not found" |
| warning PHP (colonna inesistente) | ⚠️ success=True ma data è una stringa HTML: controlla il tipo |
I record dei elenchi sono NavigableRecord: accesso per attributo (rec.codice,
rec.indirizzo.citta per i campi annidati). Non esiste rec.get("codice").
resp = client.get_table("product").page(limit=5).search()
if resp.success and hasattr(resp.data, "records"):
for rec in resp.data.records:
print(rec.codice, rec.descri)
Cinque regole d'oro
- Controlla sempre
resp.success— gli errori HTTP/rete diventanosuccess=False, niente eccezioni. - Record dagli elenchi → attributi (
rec.campo), mai.get(). - I metodi dichiarati
-> List[…]in realtà ritornanoApiResponse: leggiresp.data.records. - Mai
lknei filtri (ignorato dal server):cs= contiene,eq= uguale. create()completa da solo il payload: legge lo schemacreate-{t}da/openapie valorizza tutte le colonne tranneid(autoincrement, tornato comeresp.data) — tu passi solo quelle che ti servono. Puoi passaredatetime.date/datetime/Decimal: vengono convertiti in stringhe (formato serverYYYY-MM-DD HH:MM:SS), perchéjson.dumpsnon accetta oggetti.companynon è una colonna: non va nel payload.- Su
customerilcodicelo calcola la libreria (progressivomasclidigaz_aziend):create()einsert_record()ignorano il codice che passi e generano il prossimo del mastro (es.103000009), riprovando se il server risponde409 Duplicate key.
Adattare GAzie a CRUD PHP API
Per adattare il database GAzie a php-crud-api occorre inserire il campo id come chiave primaria
ove non vi sia (php-crud-api lo richiede per gli URL /records/{tabella}/{id}).
Procedura da eseguire sul DB GAzie
DELIMITER //
DROP PROCEDURE IF EXISTS AddIdPrimaryKeyToGazie //
CREATE PROCEDURE AddIdPrimaryKeyToGazie()
BEGIN
-- =========================================================================
-- 1. TUTTE LE DICHIARAZIONI (Devono stare in cima)
-- =========================================================================
DECLARE done INT DEFAULT FALSE;
DECLARE current_table VARCHAR(255);
DECLARE old_pk_columns VARCHAR(512);
-- Cursore per escludere tabelle con 'id' o con qualsiasi altro AUTO_INCREMENT
DECLARE table_cursor CURSOR FOR
SELECT t.TABLE_NAME
FROM information_schema.TABLES t
WHERE t.TABLE_SCHEMA = DATABASE()
AND t.TABLE_NAME LIKE 'gaz_%'
AND NOT EXISTS (
SELECT 1
FROM information_schema.COLUMNS c
WHERE c.TABLE_SCHEMA = DATABASE()
AND c.TABLE_NAME = t.TABLE_NAME
AND c.COLUMN_NAME = 'id'
)
AND NOT EXISTS (
SELECT 1
FROM information_schema.COLUMNS c
WHERE c.TABLE_SCHEMA = DATABASE()
AND c.TABLE_NAME = t.TABLE_NAME
AND c.EXTRA LIKE '%auto_increment%'
);
-- L'handler deve essere l'ultima cosa dichiarata
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- =========================================================================
-- 2. ISTRUZIONI ESEGUIBILI
-- =========================================================================
-- Creazione della tabella temporanea per il LOG
DROP TEMPORARY TABLE IF EXISTS temp_log_alter_tables;
CREATE TEMPORARY TABLE temp_log_alter_tables (
id INT AUTO_INCREMENT PRIMARY KEY,
eseguito_alle TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
tabella_modificata VARCHAR(255),
query_eseguita TEXT
);
OPEN table_cursor;
read_loop: LOOP
FETCH table_cursor INTO current_table;
IF done THEN
LEAVE read_loop;
END IF;
-- Recupera dinamicamente le colonne che compongono l'attuale chiave primaria
SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ', ')
INTO old_pk_columns
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = current_table
AND CONSTRAINT_NAME = 'PRIMARY';
-- Se esiste una vecchia chiave primaria, procediamo
IF old_pk_columns IS NOT NULL THEN
SET @dynamic_sql = CONCAT(
'ALTER TABLE `', current_table, '` ',
'DROP PRIMARY KEY, ',
'ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST, ',
'ADD UNIQUE KEY `uk_', current_table, '_old_pk` (', old_pk_columns, ');'
);
-- Scrittura nel LOG
INSERT INTO temp_log_alter_tables (tabella_modificata, query_eseguita)
VALUES (current_table, @dynamic_sql);
-- Esecuzione della query
PREPARE stmt FROM @dynamic_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END LOOP;
CLOSE table_cursor;
-- 3. Stampa a schermo del risultato finale
SELECT * FROM temp_log_alter_tables;
-- Pulizia finale
DROP TEMPORARY TABLE IF EXISTS temp_log_alter_tables;
END //
DELIMITER ;
Chiamare la procedura
CALL AddIdPrimaryKeyToGazie();
Release files for py-gazie 0.1.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| py_gazie-0.1.7.tar.gz | 87.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| py_gazie-0.1.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 216.7 kB
Release files / py_gazie-0.1.7.tar.gz
| Download URL | py_gazie-0.1.7.tar.gz |
|---|---|
| Size | 87.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
095ff8bd46fc1cd92ebf135eb83c95c9d3b1e4d3fa57c6ba0298681b3068e4ae
|
|
BLAKE2b-256 checksum How to use checksums |
a320904c4e64957e6234c0dace5314ea812c23040026ef24009f44bf754852d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / py_gazie-0.1.7-py3-none-any.whl
| Download URL | py_gazie-0.1.7-py3-none-any.whl |
|---|---|
| Size | 129.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a12026539372dfcfb03901f4efad8059f54518351617ecdb3865e0fda728eec
|
|
BLAKE2b-256 checksum How to use checksums |
f94cc7174ce1293a232880f804ddb1755dc7f117453bd68f0619571cb2eb0b9c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|