En af Wallnots få (men trofaste) brugere, bad om arkiv- og søgefunktionalitet på Wallnot.
Det krævede en større omlægning af Wallnot fra:
- En side, der viser links til et øjebliksbillede af gratisartikler fra forsiden af danske netaviser.
Til:
- En side der løbende arkiverer links til gratisartikler fra danske netaviser
Det kræver:
- En bagvedliggende database
- Løbende vedligeholdelse så links, der ændrer status fra gratis- til betalingsartikler, fjernes fra siden
Den nye Wallnot har:
- Søgefunktion på artikeloverskrifter
- Arkiv, der hele tiden bliver større
- Zetland- og delte Politiken-artikler fra de sidste par år. Zetlandarkivet er nærmest komplet.
- En robot, der løbende tjekker links fra de sidste par dage for ændret betalingsmursstatus
- Mulighed for at filtrere Ritzau-telegrammer og dubletartikler fra
- Bevaret hurtig- og enkeltheden fra version 1.
Arkitekturen bag Wallnot version 2
Version 2 af Wallnot er udviklet i Django, mens robotterne der indsamler og vedligeholder links er skrevet i Python.
Selve omlægningen til Django er faktisk enkel.
I models.py beskrives datamodellen, altså felterne i den bagvedliggende database:
from django.db import models
from django.utils import timezone
from django.contrib import admin
# Create your models here.
class Article(models.Model):
title = models.CharField('Overskrift', max_length=500)
unique_id = models.CharField('Avisens artikel-id', max_length=20, unique=True, null=True, blank=True)
date = models.DateTimeField('Publiceringstidspunkt')
MEDIUM_CHOICES = (
('politiken', 'Politiken'),
('berlingske', 'Berlingske'),
('jyllandsposten', 'Jyllandsposten'),
('information', 'Information'),
('kristeligtdagblad', 'Kristeligt Dagblad'),
('weekendavisen', 'Weekendavisen'),
('zetland', 'Zetland'),
('finansdk', 'Finans.dk'),
('borsen', 'Børsen'),
('arbejderen', 'Arbejderen'),
)
medium = models.CharField('Medie', max_length=30, choices=MEDIUM_CHOICES)
url = models.URLField('Adresse', max_length=400, unique=True)
ritzau = models.BooleanField('Ritzautelegram', default=False, null=True, blank=True)
excerpt = models.CharField('Første sætning', max_length=1000, null=True, blank=True)
duplicate = models.BooleanField('Dublet', default=False, null=True, blank=True)
user_reports_paywall = models.BooleanField('Brugerrapporteret paywall', default=False, null=True)
created_at = models.DateTimeField('Tilføjet den', default=timezone.now, editable=False)
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title','unique_id','ritzau','duplicate','excerpt','date')
list_filter = ('medium', 'user_reports_paywall', 'ritzau','duplicate')
search_fields = ['title', 'unique_id', 'excerpt']
Derudover skal der bygges et view, der beskriver forespørgslen til databasen. Her i en forkortet udgave uden logikken bag brugerrapportering af links bag paywall:
from django.shortcuts import render
from django.core.paginator import Paginator
import requests
import json
from .models import Article
def index(request):
articles = Article.objects.order_by('-date')
searchterm = request.GET.get('q')
medium = request.GET.get('m')
ritzau = request.GET.get('r')
duplicates = request.GET.get('d')
newwindow = request.GET.get('w')
if searchterm:
firstsearchcharacter = searchterm[:1]
# Exclude queries by adding ! to searchterm
if firstsearchcharacter == "!":
searchterm = searchterm[1:]
articles = articles.exclude(title__iregex=searchterm)
searchterm = "!" + searchterm
# Perform normal regex-enabled search
else:
articles = articles.filter(title__iregex=searchterm)
if medium:
articles = articles.filter(medium=medium)
if ritzau:
articles = articles.exclude(ritzau=True)
if not duplicates and not medium:
articles = articles.exclude(duplicate=True)
paginator = Paginator(articles, 80)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
context = {'request': request, 'page_obj': page_obj, 'medium': medium, 'searchterm': searchterm, 'ritzau': ritzau, 'newwindow': newwindow, 'duplicates': duplicates}
return render(request, 'wall/index.html', context)
Til sidst skrives en skabelon (template) der omsætter data til HTML. Her er fx den ganske korte bid kode, der spytter artikellinks ud på siden:
{% for article in page_obj %}
{% ifchanged article.date|date %}<h3>{{ article.date|date }}</h3>{% endifchanged %}
<p>{{ article.date|date:"H:i" }}: <a href="{{ article.url }}"{% if newwindow %} target="_blank"{% endif %}>{{ article.title }}</a> {% if article.ritzau %}<small><sup> ritzau </sup></small> {% endif %}{% if article.duplicate and not medium %}<small><sup> dublet </sup></small> {% endif %}<img title="Giv besked hvis artiklen er bag en paywall" id="{{ article.id }}" class="myBtnt" src="{% static "wall/alert.svg" %}"/></p>
{% endfor %}
God fornøjelse med den nye Wallnot!