Django comes with a syndication framework that lets you create RSS and Atom feeds easily1. If you already have your model set up all you need to do is subclass the Feed class, add it to your urls.py, and map your model's fields to the XML fields:

class PodcastFeed(Feed):
    copyright_text = "Copyright (C) 2021, In Shape Mind"
    title = "In Shape Mind Podcast"
    link = "/podcast/"
    description = "News articles, transcribed from text, from a variety of quality sources."

    def categories(self):
        return 'news', 'current events', 'trending'

    def feed_copyright(self):
        return self.copyright_text

    def items(self):
        return PodcastArticle.objects.order_by('-id')[:65]

    def item_title(self, item):
        return item.article.title

    def item_description(self, item):
        return item.article.summary

    def item_link(self, item):
        return item.mp3_file.url

    def item_author_name(self, item):
        return item.article.author

    def item_pubdate(self, item):
        return item.article.publish_date

    def item_categories(self, item):
        return item.article.keywords

Since my site2 already has tons of quality textual data, I thought why not run it through a text-to-speech program and make it a podcast app as well? In order to get this to work I created the PodcastArticle model which has a one-to-one relationship with my Article model. The only thing left to do after that was create the mp3 files with the article text data. The most difficult part was understanding that creating the model so the storage target works in development as well as production is as easy as:

from django.conf import settings
if not settings.DEBUG:
    from inshapemind.storage_backends import PublicMediaStorage


def select_storage():
    return FileSystemStorage() if settings.DEBUG else PublicMediaStorage()


class PodcastArticle(models.Model):
    article = models.OneToOneField('djangonewspaper.NewspaperArticle', null=True, on_delete=models.SET_NULL)
    mp3_file = models.FileField(upload_to='podcasts/', storage=select_storage())

I needed to be selective about which articles I transcribed to audio to keep the quality high, so I just created a celery task and inserted it into the part of my application that searches articles for "trending" keywords (but also filters on completeness of data). So now my celery workers can create a corresponding PodcastArticle object & mp3 file (hosted on CDN) that is added to my Podcast RSS feed. I think I wrote ~ 100 lines of code in all. Cool!