Case Study Django + Blockchain: come ho costruito il backend di SchoolPlatform (DRF, JWT, web3.py)

Introduzione

Se vuoi far parlare un database relazionale con una blockchain pubblica senza far impazzire gli utenti a colpi di gas fee, devi scegliere bene cosa va on-chain e cosa resta off-chain. In questo case study ti mostro come ho costruito il backend di SchoolPlatform con Django 4.2, Django REST Framework, JWT e web3.py su Polygon: pattern architetturali, service layer per mint/burn, caching dei saldi e test sui costi reali. Niente magie, solo scelte tecniche concrete che puoi copiare e adattare.


Perché Django per un LMS con token su blockchain

Ho scelto Django 4.2 per tre motivi:

  1. Chiarezza strutturale – App separate per utenti, corsi, pagamenti e reward.
  2. Sicurezza integrata – ORM, protezioni XSS/CSRF, validazione form.
  3. Velocità di sviluppo – Arrivare a un MVP senza reinventare la ruota.

Stack tecnico (Django 4.2, DRF, SimpleJWT, web3.py, Polygon)

  • Backend: Django 4.2 + Django REST Framework
  • Autenticazione: SimpleJWT
  • Blockchain: web3.py con RPC Polygon
  • Cache e task asincroni: Redis + Celery
  • Test e sviluppo: testnet Polygon, pytest

On-chain vs Off-chain: quando scrivere in blockchain (e quando no)

La regola:

  • On-chain → operazioni che richiedono tracciabilità immutabile (es. mint/burn token).
  • Off-chain → logica interna, bilanci temporanei, staking, sconti.

Esempio di modello per i bilanci off-chain:

class DBTeoCoinBalance(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    available_balance = models.DecimalField(max_digits=12, decimal_places=2, default=0.00)
    staked_balance = models.DecimalField(max_digits=12, decimal_places=2, default=0.00)

    def total_balance(self):
        return self.available_balance + self.staked_balance

Service layer web3.py in Django: pattern e gestione errori RPC

Esempio di modello wallet utente:

class UserWallet(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    address = models.CharField(max_length=42, unique=True)  # 0x...
    private_key = models.CharField(max_length=66)  # ⚠️ Da cifrare in produzione
    created_at = models.DateTimeField(auto_now_add=True)

    def get_masked_private_key(self):
        return f"{self.private_key[:6]}...{self.private_key[-4:]}"

Le chiavi private vanno cifrate o gestite tramite HSM/KMS.


JWT & DRF: autenticazione API per client mobile

Esempio endpoint per saldo TEO:

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_wallet_balance(request):
    user = request.user
    result = blockchain_service.get_user_wallet_balance(user)
    return Response(result)

L’uso di caching riduce latenza e chiamate RPC superflue.


Caching e sync: Redis + Celery per bilanci TEO “istantanei”

  • Redis come store temporaneo saldi.
  • Celery per sincronizzare on-chain in batch.

Sicurezza chiavi: KMS/HSM, env, rotazione, masking

  • Mai salvare private key in chiaro.
  • Rotazione periodica delle chiavi.
  • Mascheramento in UI.

Costi gas: test su testnet Polygon e ottimizzazioni

  • Test di transazioni multiple per ridurre fee.
  • Uso di funzioni smart contract ottimizzate.

Test E2E: acquisto → pagamento → accredito token

  • Integrazione acquisto corso → mint token.
  • Test gas-optimized su Polygon testnet.
  • Fallback RPC per garantire saldo corretto.

Roadmap: staking, NFT certificati, DAO corsi

  • Staking avanzato.
  • NFT come certificati di completamento.
  • DAO per governance corsi.

FAQ

Django funziona con Web3? Sì, con web3.py e pattern service layer. Come gestire le chiavi? Con KMS/HSM o cifratura asimmetrica. Quanto costa il mint? Dipende da gas price su Polygon; in media pochi centesimi.


Conclusione

SchoolPlatform dimostra che un backend Django può integrarsi con blockchain in modo fluido e user-friendly. Il trucco sta nel bilanciamento tra on-chain e off-chain, nella gestione sicura delle chiavi e in un’architettura modulare che separa responsabilità.

💬 E tu? Hai mai dovuto sincronizzare un DB con una blockchain? Che approccio hai scelto?

Grazie per essere arrivato fino alla fine!

Matteo Ricci - Full Stack Developer