Estendi la tua applicazione

Abbiamo completato i passi necessari per la creazione del nostro sito: sappiamo come scrivere un modello, una url, una view ed un template. Sappiamo anche come far diventare carino il nostro sito.

Ora di far pratica!

La prima cosa di cui abbiamo bisogno nel nostro blog è, ovviamente, una pagina per rendere visibile un post, vero?

Abbiamo già un modello dei Post, quindi non abbiamo bisogno di aggiungere niente in models.py.

Creare un link di template verso la pagina di dettaglio di un post

Cominceremo aggiungendo un link all'interno del file blog/templates/blog/post_list.html. Per ora dovrebbe avere questo aspetto:

{% extends 'blog/base.html' %}

{% block content %}
    {% for post in posts %}
        <div class="post">
            <div class="date">
                {{ post.published_date }}
            </div>
            <h1><a href="">{{ post.title }}</a></h1>
            <p>{{ post.text|linebreaks }}</p>
        </div>
    {% endfor %}
{% endblock content %}

Vogliamo creare un link che dal titolo di un post facente parte dell'elenco di articoli porti alla pagina di dettaglio. Cambiamo <h1><a href="">{{ post.title }}</a></h1> così che linki alla pagina di dettaglio del post:

<h1><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1>

È arrivata l'ora di spiegare il misterioso {% url 'post_detail' pk=post.pk %}. Come avrai capito, il simbolo {% %} significa che stiamo usando i tag del template di Django. Questa volta ne useremo uno che creerà una URL per noi!

blog.views.post_detail è un percorso per arrivare alla post_detail view che vogliamo creare. Nota bene: blog è il nome della nostra applicazione (la directory blog), views viene dal nome del file views.py e l'ultima cosa - post_detail - è il nome della view.

Adesso quando andremo all'indirizzo: http://127.0.0.1:8000/ avremo un errore (come sapevamo, dal momento che non abbiamo una URL oppure una view per post_detail). Avrà questo aspetto:

Errore: nessuna corrispondenza inversa

Crea una URL per i dettagli di un post

Creiamo una URL in urls.py per il nostro post_detail view!

Vogliamo che il nostro primo post venga visualizzato a questo URL : http://127.0.0.1:8000/post/1/

Facciamo sì che l'URL nel file blog/urls.py punti Django ad una view chiamata post_detail, che mostrerà un intero post. Aggiungi la riga url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'), al file blog/urls.py. Il file dovrebbe assomigliare a questo:

from django.conf.urls import include, url
from . import views

urlpatterns = [
    url(r'^$', views.post_list, name='post_list'),
    url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'),
]

Questa parte ^post/(?P<pk>[0-9]+)/$ sembra spaventosa, ma non preoccuparti - te la spiegheremo: - inizia ancora con ^ -- "l'inizio" - post/ semplicemente significa che dopo l'inizio, l'URL dovrebbe contenere la parola post e /. Fin qui tutto bene. - (?P<pk>[0-9]+) - questa parte è più complicata. Significa che Django prenderà tutto quello che hai messo qui e lo trasferirà ad una view come variabile denominata pk. [0-9] ci dice anche che la variabile può essere solo un numero, non una lettera (quindi tutto tra 0 e 9). + significa che ci devono essere una o più cifre. Quindi qualcosa di simile a http://127.0.0.1:8000/post// non è valido, ma http://127.0.0.1:8000/post/1234567890/ è perfetto! - / Quindi ci serve / di nuovo - $ - "fine"!

Ciò significa che se digiti http://127.0.0.1:8000/post/5/ nel tuo browser, Django capirà che stai cercando una view chiamata post_detail e trasferirà l'informazione che pk è uguale a 5 a quella view.

pk è un diminutivo di primary key. Questo nome viene frequentemente utilizzato nei progetti Django. Ma puoi chiamare la tua variabile come vuoi (ricorda: minuscole e _ invece degli spazi!). Per esempio invece di (?P<pk>[0-9]+) potremmo avere la variabile post_idquindi questo pezzettino dovrebbe assomigliare a: (?P<post_id>[0-9]+).

Ok, abbiamo aggiunto un nuovo schema di URL a blog/urls.py! Aggiorniamo la pagina: http://127.0.0.1:8000/ Boom! Ancora un altro errore! Come previsto!

Errore attributo

Ti ricordi di quale è il prossimo passo? Ma certo: aggiungere una view!

Aggiungi una view del post

Questa volta alla nostra view viene data un altro parametro pk. La nostra view deve prenderlo, vero? Quindi definiremo la nostra funzione come def post_detail(request, pk):. Dobbiamo utilizzare esattamente lo stesso nome che abbiamo specificato in urls (pk). Omettere questa variabile è sbagliato e genererà un errore!

Ora, noi vogliamo ottenere un' unico post. Per farlo possiamo utilizzare le queryset così:

Post.objects.get(pk=pk)

Ma questo codice presenta un problema. Se non c'è Post con primary key (pk) otterremo un errore bruttissimo!

Errore: non esiste

Noi non lo vogliamo! Ma, senza dubbio, Django ha qualcosa che si occuperà del problema per noi: get_object_or_404. Nel caso in cui non ci sia Post con la data pk mostrerà una pagina molto più carina (chiamata Page Not Found 404).

Pagina non trovata

La buona notizia è che in realtà puoi creare la tua pagina Page not found modificarla come vuoi e darle un bell'aspetto. Ma non è importantissimo in questo momento, quindi salteremo questa parte.

Ok, è arrivata l'ora di aggiungere una view al nostro file views.py!

Dovremo aprire blog/views.py ed aggiungere il seguente codice:

from django.shortcuts import render, get_object_or_404

Vicino ad altre righe from ed alla fine del file aggiungeremo la nostra view:

    def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_detail.html', {'post': post})

Si. E' giunta l'ora di aggiornare la pagina: http://127.0.0.1:8000/

Visualizzazione elenco post

Ha funzionato! Ma cosa succede se clicchi su un link nel titolo del post?

Errore: il template non esiste

Oh no! Un altro errore! Ma sappiamo già come occuparcene, giusto? Dobbiamo aggiungere un template!

Crea un template per il post detail

Creeremo un file in blog/templates/blog chiamato post_detail.html.

Il risultato somiglierà a questo:

{% extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.published_date %}
            <div class="date">
                {{ post.published_date }}
            </div>
        {% endif %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.text|linebreaks }}</p>
    </div>
{% endblock %}

Stiamo estendendo ancora una volta il template di base. base.html. Nel blocco content vogliamo mostrare una published_date del post (se esiste), un titolo ed il testo. Ma dovremmo discutere di alcune cose importanti, vero?

{% if ... %} ... {% endif %} è un tag di template che possiamo utilizzare quando vogliamo controllare qualcosa (ricordi if ... else .. dal capitolo Introduzione a Python?). In questo caso vogliamo controllare che la published_date di un post non sia vuota.

Ok, possiamo aggiornare la nostra pagina e vedere se Page not found non c'è più.

Pagina di dettaglio del post

Si! Ha funzionato!

Ultima cosa: ora di fare il deploy!

Sarebbe bello vedere se il tuo sito Web sarà ancora funzionante in PythonAnywhere, vero? Proviamo a fare un alrto deploy.

$ git status
$ git add -A .
$ git status
$ git commit -m "Added view and template for detailed blog post as well as CSS for the site."
$ git push
$ cd my-first-blog
$ source myvenv/bin/activate
(myvenv)$ git pull
[...]
(myvenv)$ python manage.py collectstatic
[...]
  • Infine, vai su il Web tab e premi Reload.

Fatto! Congratulazioni :)