Vai al contenuto principale
BlogBasi di datiCome Django fa il lavoro pesante per l'SQL

Come Django fa il lavoro pesante per l'SQL

Come Django fa il lavoro pesante - Testata del blog

Pythone soprattutto Django, sono essenziali per costruire applicazioni più efficienti, con meno codice e collegate a un database altamente scalabile. Sono qui per parlarvi di come ridurre l'attrito quotidiano che deriva dalla costruzione e dal supporto di applicazioni moderne utilizzando SQL e Python per astrarre la complessità e rendere il nostro lavoro e la nostra vita un po' più semplici.

Senza entrare nel merito, possiamo ipotizzare:

  • SQL è ottimizzato per i database SQL
  • Python non è ottimizzato per i database SQL

Questo esercizio supporta direttamente l'ebook Understanding Databases e la mia nuova serie didattica Linode LIVE! utilizzando Python e gli strumenti Pythonic per eseguire comandi in SQL grezzo senza la necessità di scrivere effettivamente SQL. Sto usando la modellazione dei dati di Django, ma la sintassi è molto simile a quella del pacchetto SQLAlchemy di Python.

Cominciamo!
Ecco un esempio di modello di dati Django:

class BlogArticle(models.Model):
    user = models.ForeignKey(User, default=1, on_delete=models.SET_DEFAULT)
    title = models.CharField(max_length=120)
    slug = models.SlugField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)
    publish_timestamp = models.DateTimeField(
        auto_now_add=False,
        auto_now=False,
        blank=True,
        null=True,
    )

Supponiamo che questo modello viva in un'applicazione Django chiamata Articles (Le applicazioni Django sono essenzialmente componenti che costituiscono la totalità di un progetto Django).

Ora abbiamo due nomi con cui lavorare:

  • Articles (nome dell'applicazione)
  • BlogArticle (nome del modello)

In combinazione, questi si traducono nel nome della tabella SQL:

articles_blog_article

Django fa questa magia per noi.

Se si utilizzasse la shell di MySQL si vedrebbe:

mysql> SHOW TABLES;
+------------------------------+
| Tables_in_cfe_django_blog_db |
+------------------------------+
| articles_blog_article        |
| auth_group                   |
| auth_group_permissions       |
| auth_permission              |
| auth_user                    |
| auth_user_groups             |
| auth_user_user_permissions   |
| django_admin_log             |
| django_content_type          |
| django_migrations            |
| django_session               |
+------------------------------+
11 rows in set (0.01 sec)

Ora diamo un'occhiata alle colonne del nostro modello Django:

mysql> DESCRIBE articles_blog_article;
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | bigint       | NO   | PRI | NULL    | auto_increment |
| title                  | varchar(120) | NO   |     | NULL    |                |
| slug                   | varchar(50)  | YES  | MUL | NULL    |                |
| content                | longtext     | YES  |     | NULL    |                |
| publish_timestamp      | datetime(6)  | YES  |     | NULL    |                |
| user_id                | int          | NO   | MUL | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)

A parte la scrittura di una configurazione di base, Django ha fatto tutto il lavoro SQL al posto nostro in questo database MySQL. In realtà, la maggior parte di questo esercizio non è stata pensata per mettere in evidenza Django o Python come sostituto di SQL, ma per ricordare che le astrazioni funzionano.

L'ascesa di Python e il costo dell'attrito

Parliamo del percorso di minor resistenza e del perché ritengo che Python sia uno dei modi migliori per sfruttare SQL.

È molto facile scrivere, leggere, eseguire e spedire Python. Se si cambia "Python" con qualsiasi altro paradigma di programmazione, è quasi impossibile fare la stessa affermazione. Anche JavaScriptè un concorrente, ma viene sempre confuso con Java. Mi rendo conto che queste sono generalizzazioni e non sono sempre vere, ma sono problemi comuni che si presentano durante lo sviluppo di un'applicazione.

Credo che queste generalizzazioni tendano a essere vere a causa della sintassi inglese di Python.

Confrontiamo un'istruzione SQL con un'istruzione Python e Django:

  • SQL: SELECT * from articles_blog_article;
  • Python e Django: items = BlogArticle.objects.all()

Entrambe le istruzioni restituiscono gli stessi dati. L'istruzione Python , tuttavia, restituisce un elenco di oggetti Python (items) che quasi tutti gli sviluppatori di Python , con diverse esperienze, possono utilizzare. I risultati SQL grezzi devono essere convertiti prima di essere utilizzati in un'applicazione Python .

Descrizioni dei campi
Se osserviamo più da vicino la descrizione di questo campo SQL:

+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| title                  | varchar(120) | NO   |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+

Rispetto alla descrizione di questo campo di Django:

title = models.CharField(max_length=120)

  • Quale dei due ha più attrito?
  • Quale dei due è più facile da capire?

Che fornisce informazioni sufficienti?

Se non si è un codificatore e si vede varchar(120)Cosa ne pensi? Sono abbastanza sicuro che possiate almeno indovinare che cosa max_length=120 means. Il bello è che hanno lo stesso significato: limitare questo campo a 120 caratteri o meno.

Aggiunta di dati al database

Con Django:

BlogArticle.objects.create(
    title="Hello World",
    content="Coming Soon",
    slug="hello-world",
    publish_timestamp=None,
)

Con SQL:

INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`) 
VALUES (1, 'Hello World', 'hello-world', 'Coming Soon', NULL);

Per quanto riguarda la semplicità e la chiarezza, credo che il vincitore sia sicuramente Django e Python. title = "Hello World" è più facile che capire cosa succede con il valore della colonna (campo) equivalente in SQL. Non c'è dubbio che il modo in cui è scritto in SQL è molto efficace se si sa cosa si sta facendo.

Aggiungere più righe
con Django:

items = [
    BlogArticle(title='Hello Again 0', slug='hello-again-0', content="Coming Soon"),
    BlogArticle(title='Hello Again 1', slug='hello-again-1', content="Coming Soon"),
    BlogArticle(title='Hello Again 2', slug='hello-again-2', content="Coming Soon"),
    BlogArticle(title='Hello Again 3', slug='hello-again-3', content="Coming Soon"),
    BlogArticle(title='Hello Again 4', slug='hello-again-4', content="Coming Soon"),
]
BlogArticle.objects.bulk_create(items)

Con SQL:

INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`) 
VALUES (1, 'Hello Again 0', 'hello-again-0', 'Coming Soon', NULL),
    (1, 'Hello Again 1', 'hello-again-1', 'Coming Soon', NULL),
    (1, 'Hello Again 2', 'hello-again-2', 'Coming Soon', NULL),
    (1, 'Hello Again 3', 'hello-again-3', 'Coming Soon', NULL),
    (1, 'Hello Again 4', 'hello-again-4', 'Coming Soon', NULL);

Ancora una volta, il codice di Python è più leggibile, mentre il codice SQL fornisce maggiori informazioni sui dati reali. E, ancora una volta, Python sta scrivendo il codice SQL per noi utilizzando il codice Django di cui sopra. Piuttosto interessante, no?

Il motivo per cui mi sono imbarcato in questo confronto non è quello di scegliere quale sia il modo migliore per sfruttare i database SQL, ma di evidenziare la capacità di Pythondi aiutare a ridurre l'overhead di imparare a scrivere direttamente SQL grezzo.

Esistono diversi pacchetti Python che scrivono essenzialmente l'SQL grezzo per voi, eccone alcuni:

  • Django
  • Panda
  • SQLAlchemy
  • Polari
  • Dask
  • Vaex
  • Pythondel modulo CSV integrato
  • ORM a tartaruga
  • Pony ORM
  • Oggetto SQLO

Django fa il lavoro pesante
I pacchetti di mappatura oggetti-relazionali (comunemente chiamati ORM) sono la salsa segreta che permette a Python di sfruttare i database SQL. Penso a un ORM come a un intermediario che aiuta a spostare i dati nella sintassi nativa di un determinato linguaggio di programmazione.

All'inizio di questo esercizio abbiamo iniziato a vedere come questo si traduce in Django, ma ora approfondiamo l'argomento.

Supponiamo di avere dei dati nel nostro database, possiamo scrivere un comando come questo:

my_post = BlogArticle.objects.first()
Questa istruzione interrogherà il nostro database, estrarrà i dati, li caricherà in un'istanza di un oggetto Python Classe assegnarlo alla variabile my_post.

Da qui si può procedere in questo modo:

# using a django-managed python shell
# via python manage.py shell
>>> print(my_post.title)
Hello World

In questo caso, abbiamo usato la notazione a punti per accedere al file title che è stato dichiarato nel campo BlogPost modello Django della sezione precedente. Questo campo corrisponde a una colonna della nostra tabella del database SQL articles_blog_article.

Grazie all'ORM, possiamo farlo:

>>> my_post.title = "some other title"

In questo esempio di sessione di shell Python , l'opzione my_post.title ora sempre essere "some other title". Il database SQL sottostante, tuttavia, continua a riconoscere questi stessi dati come Hello World. Il database manterrà i dati originali fino a quando Python non effettuerà il commit (aka .save()) questa modifica dei dati al database. Se Python non esegue mai il commit di questi dati, essi non saranno mai aggiornati nel database. Questo fa parte della magia dell'ORM. Possiamo utilizzo e cambiamento i dati senza influenzare i dati memorizzati. Quando vogliamo modificare ciò che accade effettivamente nel database, eseguiamo:

>>> my_post.title = "some other title again"
>>> my_post.save()

Dopo aver eseguito .save() il nostro database, per questa particolare riga, aggiornerà il titolo della colonna in modo che corrisponda esattamente a ciò che è scritto come stringa Python qui sopra. Non dimenticate che l'elemento .save() è specifico per effettuare i commit al database nei modelli Django. .save() non significa nulla per un Python Class senza che prima erediti una classe Django Model.

Costruire con Django, MySQL e Linode

Questo è uno dei tanti esempi di come Django faccia il lavoro pesante per voi. Se siete interessati a un approccio moderno alla distribuzione di applicazioni Django su Linode, con un database MySQL gestito, GitHub Actions per CI/CD, Terraform e Ansible, date un'occhiata ai seguenti contenuti ora disponibili su Linode:

Per aiutarvi a iniziare, su GitHub Coding for Entrepreneurs c'è un repository di codice che accompagna ogni passo della serie. Buona fortuna e fatemi sapere come vanno le cose via Twitter @JustinMitchel.

Commenti

Lascia una risposta

Il vostro indirizzo e-mail non sarà pubblicato. I campi obbligatori sono contrassegnati da *