{"id":23081006,"url":"https://github.com/xurble/django-feed-reader","last_synced_at":"2025-08-15T23:31:05.521Z","repository":{"id":57420070,"uuid":"189869239","full_name":"xurble/django-feed-reader","owner":"xurble","description":"An RSS/Atom/JSONFeed reading + storing library for Django","archived":false,"fork":false,"pushed_at":"2024-05-11T06:09:51.000Z","size":247,"stargazers_count":46,"open_issues_count":2,"forks_count":20,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-26T18:24:40.322Z","etag":null,"topics":["atom","django","jsonfeed","rss"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xurble.png","metadata":{"files":{"readme":"readme.rst","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/cloudflare_worker.js","governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-06-02T16:24:05.000Z","updated_at":"2025-06-21T04:29:15.000Z","dependencies_parsed_at":"2024-02-24T09:25:06.072Z","dependency_job_id":"296f61a1-ec54-4cc3-89af-20f926f0e116","html_url":"https://github.com/xurble/django-feed-reader","commit_stats":{"total_commits":45,"total_committers":3,"mean_commits":15.0,"dds":0.1333333333333333,"last_synced_commit":"a06b14cd50b8cc55f49f4afc34230af4ed4c16d7"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/xurble/django-feed-reader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xurble%2Fdjango-feed-reader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xurble%2Fdjango-feed-reader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xurble%2Fdjango-feed-reader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xurble%2Fdjango-feed-reader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xurble","download_url":"https://codeload.github.com/xurble/django-feed-reader/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xurble%2Fdjango-feed-reader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270644764,"owners_count":24621332,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["atom","django","jsonfeed","rss"],"created_at":"2024-12-16T13:44:29.834Z","updated_at":"2025-08-15T23:31:05.067Z","avatar_url":"https://github.com/xurble.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Django Feed Reader\n==================\n\nThis is a simple Django module to allow you subscribe to RSS (and other) feeds.\n\nThis app has no UI, it just reads and stores the feeds for you to use as you see fit.\n\nThis app builds on top of the FeedParser library to provide feed management, storage, scheduling etc.\n\nFeatures\n--------\n\n* Consumes RSS, Atom and JSONFeed feeds.\n* Parses feeds liberally to try and accomodate simple errors.\n* Will attempt to bypass Cloudflare protection of feeds\n* Supports enclosure (podcast) discovery\n* Automatic feed scheduling based on frequency of updates\n\n\nInstallation\n------------\n\n``django-feed-reader`` is written in Python 3 and supports Django 2.2+\n\n- ``pip install django-feed-reader``\n- Add ``feeds`` to your ``INSTALLED_APPS``\n- Setup some values in ``settings.py`` so that your feed reader politely announces itself to servers\n   - Set ``FEEDS_USER_AGENT`` to the name and (optionally version) of your service e.g. ``\"ExampleFeeder/1.2\"``\n   - Set ``FEEDS_SERVER`` to preferred web address of your service so that feed hosts can locate you if required e.g. ``https://example.com``\n- Setup a mechanism to periodically refresh the feeds (see below)\n\nOptional Settings\n^^^^^^^^^^^^^^^^^\n\n- ``FEEDS_VERIFY_HTTPS`` (Default True)\n   - Older versions of this library did not verify https connections when fetching feeds.\n     Set this to ``False`` to revert to the old behaviour.\n- ``KEEP_OLD_ENCLOSURES`` (Default False)\n   - Some feeds (particularly podcasts with Dynamic Ad Insertion) will change their enclosure\n     urls between reads.  By default, old enclosures are deleted and replaced with new ones.\n     Set this to true, to retain old enclosures - they will have their ``is_current`` flag\n     set to ``False``\n- ``SAVE_JSON`` (Default False)\n   - If set, Sources and Posts will store a JSON representation of the all the data retrieved\n     from the feed so that uncommon or custom attributes can be retrieved.  Caution - this will\n     dramatically increase tha amount of space used in your database.\n- ``DRIPFEED_KEY`` (Default None)\n   - If set to a valid Dripfeed API Key, then feeds that are blocked by Cloudflare will\n     be automatically polled via `Dripfeed \u003chttps://dripfeed.app\u003e`_ instead.\n\n\nBasic Models\n------------\n\nA feed is represented by a ``Source`` object which has (among other things) a ``feed_url``.\n\nTo start reading a feed, simply create a new ``Source`` with the desired ``feed_url``\n\n``Source`` objects have ``Post`` children  which contain the content.\n\nA ``Post`` may have ``Enclosure`` (or more) which is what podcasts use to send their audio.\nThe app does not download enclosures, if you want to do that you will need to do that in your project\nusing the url provided.\n\n\nRefreshing feeds\n----------------\n\nTo conserve resources with large feed lists, the module will adjust how often it polls feeds\nbased on how often they are updated.  The fastest it will poll a feed is every hour. The\nslowest it will poll is every 24 hours.\n\nSources that don't get updated are polled progressively more slowly until the 24 hour limit is\nreached.  When a feed changes, its polling frequency increases.\n\nYou will need to decided how and when to run the poller.  When the poller runs, it checks all\nfeeds that are currently due.  The ideal frequency to run it is every 5 - 10 minutes.\n\nPolling with cron\n-----------------\n\nSet up a job that calls ``python manage.py refreshfeeds`` on your desired schedule.\n\nBe careful to ensure you're running out of the correct directory and with the correct python environment.\n\nPolling with celery\n-------------------\n\nCreate a new celery task and schedule in your app (see the celery documentation for details).  Your ``tasks.py`` should look something like this:\n\n::\n\n  from celery import shared_task\n  from feeds.utils import update_feeds\n\n  @shared_task\n  def get_those_feeds():\n\n    # the number is the max number of feeds to poll in one go\n    update_feeds(30)\n\n\nTracking read/unread state of feeds\n-----------------------------------\n\nThere are two ways to track the read/unread state of feeds depending on your needs.\n\n\nSingle User Installations\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf your usage is just for a single user, then there are helper methods on a Source\nto track your read state.\n\nAll posts come in unread.  You can get the current number of unread posts from\n``Source.unread_count``.\n\nTo get a ResultSet of all the unread posts from a feed call ``Source.get_unread_posts``\n\nTo mark all posts on a fed as read call ``Source.mark_read``\n\nTo get all of the posts in a feed regardless of read status, a page at a time call\n``Source.get_paginated_posts`` which returns a tuple of (Posts, Paginator)\n\nMulti-User Installations\n^^^^^^^^^^^^^^^^^^^^^^^^\nTo allow multiple users to follow the same feed with individual read/unread status,\ncreate a new ``Subscription`` for that Source and User.\n\nSubscription has the same helper methods for retrieving posts and marking read as\nSource.\n\nYou can also arrange feeds into a folder-like hierarchy using Subscriptions.\nEvery Subscription has an optional ``parent``.  Subscriptions with a ``None`` parent\nare considered at the root level.  By convention, Subscriptions that are acting as parent\nfolders should have a ``None`` ``source``\n\nSubscriptions have a ``name`` field which by convention should be a display name if it is\na folder or the name of the Source it is tracking.  However this can be set to any\nvalue if you want to give a personally-meaningful name to a feed who's name is cryptic.\n\nThere are two helper methods in the ``utils`` module to help manage subscriptions as folders.\n``get_subscription_list_for_user`` will return all Subscriptions for a User where the\nparent is None.  ``get_unread_subscription_list_for_user`` will do the same but only returns\nSubscriptions that are unread or that have unread children if they are a folder.\n\nCloudflare Busting\n------------------\ndjango-feed-reader has Dripfeed support built in.  If a feed becomes blocked by Cloudflare\nit can be polled via Dripfeed instead.  This requires a `Dripfeed \u003chttps://dripfeed.app\u003e`_\naccount and API key.\n\nFor more details see the `full documentation \u003chttps://django-feed-reader.readthedocs.io\u003e`_.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxurble%2Fdjango-feed-reader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxurble%2Fdjango-feed-reader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxurble%2Fdjango-feed-reader/lists"}