|
1 | 1 | from datetime import datetime, time |
| 2 | +from typing import TYPE_CHECKING, Any, Optional |
2 | 3 |
|
3 | 4 | from django.contrib.syndication.views import Feed |
4 | 5 |
|
|
7 | 8 | from .models import BlogPage |
8 | 9 |
|
9 | 10 |
|
| 11 | +if TYPE_CHECKING: |
| 12 | + from django.http import HttpRequest, HttpResponse |
| 13 | + |
| 14 | + from wagtail.query import PageQuerySet |
| 15 | + |
10 | 16 | # Main blog feed |
11 | 17 |
|
12 | 18 |
|
13 | 19 | class BlogFeed(Feed): |
14 | 20 | title = "The Torchbox Blog" |
15 | | - link = "/blog/" |
| 21 | + link = "/news/" |
16 | 22 | description = "The latest news and views from Torchbox on the work we do, the web and the wider world" |
17 | | - |
18 | | - def items(self): |
19 | | - return BlogPage.objects.live().public().order_by("-date")[:10] |
20 | | - |
21 | | - def item_title(self, item): |
| 23 | + request: Optional["HttpRequest"] = None |
| 24 | + |
| 25 | + def __call__( |
| 26 | + self, request: "HttpRequest", *args: Any, **kwargs: Any |
| 27 | + ) -> "HttpResponse": |
| 28 | + self.request = request |
| 29 | + |
| 30 | + return super().__call__(request, *args, **kwargs) |
| 31 | + |
| 32 | + def items(self) -> "PageQuerySet[BlogPage]": |
| 33 | + return ( |
| 34 | + BlogPage.objects.live() |
| 35 | + .public() |
| 36 | + .defer_streamfields() |
| 37 | + .select_related("feed_image") |
| 38 | + .prefetch_related("authors__author") |
| 39 | + .order_by("-date")[:10] |
| 40 | + ) |
| 41 | + |
| 42 | + def item_title(self, item: BlogPage) -> str: |
22 | 43 | return item.title |
23 | 44 |
|
24 | | - def item_description(self, item): |
25 | | - return item.listing_summary |
| 45 | + def item_description(self, item: BlogPage) -> str: |
| 46 | + return item.listing_summary or item.search_description |
26 | 47 |
|
27 | | - def item_link(self, item): |
28 | | - return item.get_full_url() |
| 48 | + def item_link(self, item: BlogPage) -> str: |
| 49 | + return item.get_full_url(request=self.request) |
29 | 50 |
|
30 | | - def item_author_name(self, item): |
31 | | - pass |
| 51 | + def item_author_name(self, item: BlogPage) -> str | None: |
| 52 | + return ( |
| 53 | + ", ".join([author_item.author.name for author_item in item.authors.all()]) |
| 54 | + or None |
| 55 | + ) |
32 | 56 |
|
33 | | - def item_pubdate(self, item): |
| 57 | + def item_pubdate(self, item: BlogPage) -> datetime: |
34 | 58 | return datetime.combine(item.date, time()) |
35 | 59 |
|
36 | | - def item_enclosure_url(self, item): |
| 60 | + def item_enclosure_url(self, item: BlogPage) -> str | None: |
37 | 61 | if item.feed_image: |
38 | 62 | return item.feed_image.file.url |
39 | 63 |
|
40 | | - def item_enclosure_mime_type(self, item): |
| 64 | + def item_enclosure_mime_type(self, item: BlogPage) -> str | None: |
41 | 65 | if item.feed_image: |
42 | | - image_format = filetype.guess_extension(item.feed_image.file) |
43 | | - return f"image/{image_format}" |
| 66 | + try: |
| 67 | + if image_format := filetype.guess_extension(item.feed_image.file): |
| 68 | + return f"image/{image_format}" |
| 69 | + except (AttributeError, OSError, TypeError): |
| 70 | + pass |
| 71 | + |
| 72 | + return None |
44 | 73 |
|
45 | | - def item_enclosure_length(self, item): |
| 74 | + def item_enclosure_length(self, item: BlogPage) -> str | None: |
46 | 75 | if item.feed_image: |
47 | | - return item.feed_image.file.size |
| 76 | + try: |
| 77 | + return str(item.feed_image.file.size) |
| 78 | + except (AttributeError, OSError, TypeError): |
| 79 | + pass |
| 80 | + |
| 81 | + return None |
0 commit comments