09. get_absolute_url

Finora abbiamo ottenuto i link a ciascun post singolo tramite "hardcoding", ovvero specificandoli in maniera diretta, utilizzando la chiave primaria pk e lo slug di ciascun post:

<!--DOCTYPE html -->
<html>
    <body>
        {% for object in object_list %}

        <h1><a href="{% url 'singolo' slug=object.slug pk=object.pk %}">{{object.titolo}}</a></h1>

        {% endfor %}
    </body>
</html>

Ma il tutto è poco elegante e soprattutto rende il programma meno modulare, noi vogliamo che la nostra app possa essere utilizzata anche in altri progetti: cosa succederebbe se il pattern URL associato variasse anche solo di poco? Otterremo sicuramente un errore.


ATTENZIONE: L'utilizzo di una CBV (Class Based View) richiamata direttamente nel file urls.py come mostrato in questa lezione, non è tipico, seppur comunque fattibile. Normalmente, le views, sia class based che function based, vengono definite comunque all'interno del file views.py, come abbiamo visto nella lezione Architettura MTV, Urls e Views. In questo breve corso introduttivo ho cercato di trovare un compromesso tra il mostrare la gran potenza di Django nel permettere di creare web app di una certa complessità scrivendo davvero poche righe di codice. Per un corso completo, dai uno sguardo a Guida Pratica e Completa a Django, Python e Bootstrap.


Creiamo una nuova funzione in models.py che restituisca gli URL dei post

Per ovviare a questo problema torniamo ora nel nostro models.py e creiamo un metodo per la classe Post che sia in grado di restituirci l'URL del nostro post, qualunque esso sia! Per convenzione, chiameremo questo metodo get_absolute_url, e sarà basata a sua volta su una funzione presente in django.urls, la funzione reverse.

from django.urls import reverse
from django.db import models

# Create your models here.

class Post(models.Model):
    # ...

    def get_absolute_url(self):
        return reverse("singolo", kwargs={"pk": self.pk, "slug": self.slug})

A questo punto tornando nel template lista_post.html, possiamo modificare i link in maniera appropriata, richiamando su ciascun oggetto del ciclo for il metodo corrispondente get_absolute_url:

<!--DOCTYPE html -->
<html>
    <body>
        {% for object in object_list %}
            <h1><a href="{{object.get_absolute_url}}">{{object.titolo}}</a></h1>
        {% endfor %}
    </body>
</html>

Nella prossima lezione aggiungeremo un sistema di paginazione per migliorare la navigazione nella nostra homepage.