Skip to main content

An RSS feed reading library for Django.

Project description

Django Feed Reader

django-feed-reader is a reusable Django app for subscribing to, fetching, and storing RSS, Atom, and JSON Feed sources.

It is designed as a backend library, not a complete reader application. It gives you Django models, polling utilities, admin integration, and read/unread helpers so you can build your own UI, APIs, and workflows on top.

What it provides

  • RSS, Atom, and JSON Feed parsing
  • Feed storage in Django models
  • Automatic polling intervals based on feed activity
  • Feed entry and enclosure persistence
  • Single-user and multi-user read/unread tracking
  • Optional raw JSON storage for uncommon feed attributes
  • Optional Cloudflare workarounds via Dripfeed or a worker URL
  • Django admin registrations for the core models

Requirements

  • Python 3
  • Django 3.2+

Installation

Install the package:

pip install django-feed-reader

Add feeds to INSTALLED_APPS:

INSTALLED_APPS = [
    # ...
    "feeds",
]

Run migrations:

python manage.py migrate

Set at least the polite-identification settings in your Django settings:

FEEDS_USER_AGENT = "ExampleReader/1.0"
FEEDS_SERVER = "https://example.com"

FEEDS_USER_AGENT is sent on outbound feed requests. FEEDS_SERVER is included in that user agent string so feed owners can identify your service.

Quick start

Create a feed source:

from feeds.models import Source

source = Source.objects.create(
    feed_url="https://example.com/feed.xml",
)

Fetch it immediately:

from feeds.utils import read_feed

read_feed(source)
source.refresh_from_db()

Inspect the results:

source.name
source.description
source.posts.count()
source.posts.order_by("-created")[:10]

Core models

Source

Represents a single feed subscription.

Useful fields include:

  • feed_url: the URL fetched by the poller
  • site_url: the feed's corresponding website, when available
  • name: feed title
  • description: feed description / summary
  • image_url: feed icon or image
  • last_result: human-readable result of the last fetch
  • status_code: last HTTP status code seen
  • interval: next polling interval in minutes
  • live: whether the source should still be actively polled

Useful helpers include:

  • unread_count
  • get_unread_posts()
  • get_paginated_posts()
  • mark_read()

Post

Represents one item / entry from a feed.

Important fields include:

  • title
  • body
  • link
  • author
  • created
  • guid
  • image_url

Enclosure

Represents media associated with a post, such as podcast audio or image attachments.

Useful helpers include:

  • is_image
  • is_audio
  • is_video

Subscription

Represents a user following a Source.

Use Subscription when you need per-user read/unread tracking or folder-like grouping of sources.

Public utility functions

The main public API lives in feeds.utils.

read_feed(source)

Fetches one Source, parses it, and persists any changes.

Use this when:

  • you want to fetch a feed immediately after creating it
  • you are debugging a specific feed
  • you need one-off refresh behavior

update_feeds(max_feeds=3)

Polls all due Source rows, ordered by due_poll, up to max_feeds.

Use this from cron, Celery, or another scheduled task runner.

test_feed(source, cache=False)

Performs a simple reachability test for a specific feed URL without going through the full persistence flow.

Subscription helpers

  • get_subscription_list_for_user(user)
  • get_unread_subscription_list_for_user(user)

These help build folder trees and unread views for multi-user applications.

Polling behavior

The library automatically adjusts polling frequency based on whether a feed changes.

  • Fastest poll frequency: 1 hour
  • Slowest poll frequency: 24 hours

Feeds that change frequently are polled more often. Feeds that remain unchanged are polled less often.

The typical pattern is to run the poller every 5 to 10 minutes and let the library decide which sources are actually due.

Using the management command

The app includes:

python manage.py refreshfeeds

That command calls update_feeds(30).

Using Celery

from celery import shared_task
from feeds.utils import update_feeds


@shared_task
def refresh_feed_batch():
    update_feeds(30)

Read/unread tracking

There are two supported patterns.

Single-user installations

If your project is effectively for one user, you can use the helper methods directly on Source.

source.unread_count
source.get_unread_posts()
source.mark_read()

Multi-user installations

If multiple users can follow the same feed, create Subscription rows.

from django.contrib.auth import get_user_model
from feeds.models import Source, Subscription

User = get_user_model()

user = User.objects.get(username="alice")
source = Source.objects.get(feed_url="https://example.com/feed.xml")

subscription = Subscription.objects.create(
    user=user,
    source=source,
    name=source.display_name,
)

You can also create folder-like subscriptions by setting source=None and using parent relationships.

Settings

Required or strongly recommended

  • FEEDS_USER_AGENT
    • Example: "ExampleReader/1.0"
  • FEEDS_SERVER
    • Example: "https://example.com"

If FEEDS_SERVER is not set, the library will derive a default from ALLOWED_HOSTS where possible.

Optional

  • FEEDS_VERIFY_HTTPS (default: True)

    • Set to False only if you deliberately want to allow invalid HTTPS certificates.
  • FEEDS_KEEP_OLD_ENCLOSURES (default: False)

    • If a feed changes enclosure URLs over time, keep the old ones and mark them with is_current=False.
  • FEEDS_SAVE_JSON (default: False)

    • Store raw feed/parser data in the json fields on Source and Post.
    • Useful when you want access to custom or uncommon feed attributes.
    • Increases database usage.
  • FEEDS_DRIPFEED_KEY (default: unset)

    • If present, Cloudflare-blocked feeds can be retried via Dripfeed.
  • FEEDS_CLOUDFLARE_WORKER (default: unset)

    • Optional alternate fetch endpoint used for Cloudflare-blocked feeds.

Cloudflare support

When a feed responds in a way that looks like Cloudflare protection, the library can:

  • mark the source as Cloudflare-protected
  • retry through Dripfeed if FEEDS_DRIPFEED_KEY is configured
  • use FEEDS_CLOUDFLARE_WORKER if configured

What this library does not do

  • It does not ship a reader UI
  • It does not define URLs or views for your application
  • It does not download enclosure files for you
  • It does not provide a complete end-user feed reader product

Development

From a checkout:

pip install -e ".[test]"
pytest

Notes for integrators

  • refreshfeeds is intentionally small and fixed to update_feeds(30). If you need different batching behavior, call update_feeds() from your own scheduler.
  • Redirect targets are validated before being followed or persisted.
  • The app stores feed metadata and parsed content, but you remain responsible for presentation and any downstream content policies in your own application.

Documentation

Full documentation is available at django-feed-reader.readthedocs.io.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_feed_reader-2.0.1b3.tar.gz (32.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_feed_reader-2.0.1b3-py3-none-any.whl (45.2 kB view details)

Uploaded Python 3

File details

Details for the file django_feed_reader-2.0.1b3.tar.gz.

File metadata

  • Download URL: django_feed_reader-2.0.1b3.tar.gz
  • Upload date:
  • Size: 32.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.0

File hashes

Hashes for django_feed_reader-2.0.1b3.tar.gz
Algorithm Hash digest
SHA256 cbc2a425a40f871302239c6300f6d2e0609c7e3a3d7e53e57be90ee966157786
MD5 fd6b1d2f42e23b412fdfbfe54d4a536d
BLAKE2b-256 7dfbdb969cc55085d1702a436696e61de6a985fdcb6b46ccc5ff565a6f0f5b5d

See more details on using hashes here.

File details

Details for the file django_feed_reader-2.0.1b3-py3-none-any.whl.

File metadata

File hashes

Hashes for django_feed_reader-2.0.1b3-py3-none-any.whl
Algorithm Hash digest
SHA256 a13144fc20bafa48dbdae07f417aa628f5329eadd0f59053b57726dee84dde9f
MD5 db8376d03c02336acce2c3aea3285e80
BLAKE2b-256 57061076e0873f67af245948dc9dbe87887fafed185a19cfa5fb0c82e99650d8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page