Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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.

Metadata

Release files for django-feed-reader 2.0.1b5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-feed-reader 2.0.1b5
File Size Uploaded
django_feed_reader-2.0.1b5.tar.gz 33.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-feed-reader 2.0.1b5
File Interpreter ABI Platform
django_feed_reader-2.0.1b5-py3-none-any.whl Python 3 none any Details

Total release size: 80.6 kB

Release files / django_feed_reader-2.0.1b5.tar.gz

Download URL django_feed_reader-2.0.1b5.tar.gz
Size 33.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9dc2b3fea206c94d7641612a58a67192481d78bd7e71042f939bb1e1db978cd2
BLAKE2b-256 checksum
How to use checksums
85710fcbd8177cfd75cb9b11734957537fc7510762390f80bf375b3b80e32e6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.8.0

Release files / django_feed_reader-2.0.1b5-py3-none-any.whl

Download URL django_feed_reader-2.0.1b5-py3-none-any.whl
Size 46.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cde425401833b0d529a0dc32205ae37dadb2051b367fba580d10ea84e2bb3f34
BLAKE2b-256 checksum
How to use checksums
be1bc8df02c7bf5a58a0a83d645d7a754d126264a3410b36240fb16d222398fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.8.0

Release history Release notifications | RSS feed

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page