Work listing page

Add a page to list works.

In this section

  • Adding a view and template to list all works

  • How to link to an expression

  • Getting the latest expression for a work

Work listing view

On our app's homepage, we're going to list all the works.

Let's create the View code to handle this in views.py. We'll use Django's generic ListView view which does all the work for us.

views.py
from django.views.generic import ListView
from .models import Work

class WorkListView(ListView):
    model = Work

Now create the matching template. Django will automatically look for a file called templates/reader/work_list.html:

work_list.html
<html>
<head><title>All my works</title></head>
<body>
  <h1>Cape Town By-laws</h1>
  
  <table>
    {% for work in work_list %}
      <tr>
        <td>{{ work.title }}</td>
        <td>{{ work.frbr_uri }}</td>
      </tr>
    {% endfor %}
  </table>
</body>

Finally, let's add this view legislation/urls.py:

urls.py
from django.urls import path
from reader.views import *

urlpatterns = [
    path('', WorkListView.as_view(), name="home"),
]

Now we need to run our server:

python manage.py runserver

Visit http://localhost:8000 and see you list of by-laws!

We now have a basic listing page that shows the titles and FRBR URIs of all the works.

How can we create a link to read the content of a by-law? If we change the table to make the title a link, what exactly are we linking to?

Linking to an expression

Recall that a work may have multiple expressions. For example, there could be different languages and different amended versions of a work.

When we link to the content of a work, which expression are we linking to?

For our app, we want to link to the latest version of a work. We're also going to add a DEFAULT_LANGUAGE_CODE setting for the site. We'll look for expressions that are in that language first, and then fall back to any language.

Let's add a helper method latest_expression to the Work model to help us fetch the latest expression for the work.

models.py
from django.db import models
from django.conf import settings

default_language_code = settings.READER_APP_SETTINGS['DEFAULT_LANGUAGE_CODE']


class Work(models.Model):
    frbr_uri = models.CharField(max_length=512, unique=True)
    title = models.CharField(max_length=512)
    metadata = models.JSONField()

    def __str__(self):
        return f'{self.title} ({self.frbr_uri})'

    def default_expression(self):
        # first, try to get the latest expression in the default language
        expression = self.expressions.filter(language_code=default_language_code).first()
        # otherwise, get the latest expression in any other language
        if not expression:
            expression = self.expressions.first()

        return expression

Let's add the new DEFAULT_LANGUAGE_CODE to legislation/settings.py:

settings.py
# ...

READER_APP_SETTINGS = {
    'DEFAULT_LANGUAGE_CODE': 'eng',
}

Now we can update the template to link to the latest expression.

work_list.html
<html>
<head><title>All my works</title></head>
<body>
  <h1>Cape Town By-laws</h1>
  
  <table>
    {% for work in work_list %}
      <tr>
        <td>
          {% with work.default_expression as expr %}
            {% if expr %}
              <a href="{% url 'expression' expr.frbr_uri %}">{{ expr.title }}</a>
            {% else %}
              {{ work.title }}
            {% endif %}
          {% endwith %}
        </td>
        <td>{{ work.frbr_uri }}</td>
      </tr>
    {% endfor %}
  </table>
</body>

We need to add the view and URL configuration for the expression URL before these changes will work. We'll do that in the next section.

Last updated