RSS para 66 redes sociais: Facebook, Instagram, X, LinkedIn, Telegram e mais Blog Afiliado Contatos
Entrar Começar grátis
Updated: 2026-09-29
Django RSS Feeds: Set Up the Syndication Framework

Short answer: Django includes a syndication framework, django.contrib.syndication, that turns a short Python class into a valid RSS 2.0 or Atom feed. You subclass Feed, define the channel title, link and description, return your latest published objects from items(), map each object to a title, description, link and date, and add the feed to your URLconf. With stable GUIDs, timezone-aware dates, absolute image URLs and a little caching, the result is a feed that readers, aggregators and auto-posting tools can rely on.

Why a Django site should have a feed

Django is often used for custom publishing sites: company news sections, magazines, documentation portals, job boards, event listings, product catalogues and SaaS changelogs. Unlike off-the-shelf blog platforms, a custom Django project does not automatically produce an RSS feed. If nobody adds one, the site has no standard way to tell the outside world that something new has been published.

A feed solves several problems at once. Readers can follow the site in a feed reader. Partners and aggregators can pull your updates. Search and discovery tools can find new pages faster. And auto-posting services can publish each new item to social networks, messengers and team chats without any extra code on your side. For a development team, a feed is also a clean integration boundary: instead of building a separate connector for every channel, you expose one well-formed feed and let external tools consume it.

The good news is that Django makes this easy. The syndication framework has been part of Django for many years, it is well documented, and a basic feed takes a few minutes to write.

The minimal feed class

A feed in Django is a class that extends django.contrib.syndication.views.Feed. Suppose you have an Article model with a title, a summary, a slug, a publication date and a published flag. A minimal feed looks like this:

from django.contrib.syndication.views import Feed
from django.urls import reverse
from django.utils import timezone
from .models import Article

class LatestArticlesFeed(Feed):
    title = "Example Company News"
    link = "/news/"
    description = "New articles from Example Company."

    def items(self):
        return (Article.objects
                .filter(is_published=True, published_at__lte=timezone.now())
                .order_by("-published_at")[:20])

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

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

    def item_link(self, item):
        return reverse("article-detail", args=[item.slug])

    def item_pubdate(self, item):
        return item.published_at

Then add it to your URLconf:

from django.urls import path
from .feeds import LatestArticlesFeed

urlpatterns = [
    path("news/feed/", LatestArticlesFeed(), name="news-feed"),
]

Note that you pass an instance, LatestArticlesFeed(), not the class. If your model defines get_absolute_url(), you can leave out item_link(): Django uses that method by default.

Visit /news/feed/ in a browser or with curl and you should see an RSS 2.0 document with a <channel> and one <item> per article.

Absolute URLs and the sites framework

Feed consumers need absolute URLs. A link like /news/my-article/ means nothing to a feed reader or an auto-posting tool that fetched the feed from elsewhere. Django handles this for you: the syndication framework turns relative links into absolute ones using the current site’s domain.

Where that domain comes from matters. If django.contrib.sites is installed, Django uses the domain stored in the Site object for your SITE_ID. If that record still says example.com, which is the default in a fresh project, every link in your feed will point to example.com. This is one of the most common problems with new Django feeds. Check the Site record in the admin or a data migration and set the real domain.

If the sites framework is not installed, Django builds the domain from the incoming request instead. That usually works, but behind a reverse proxy it can produce internal hostnames or plain http links. Make sure ALLOWED_HOSTS, the proxy’s forwarded headers and settings such as SECURE_PROXY_SSL_HEADER are configured so Django knows the public host and scheme.

The same applies to URLs inside descriptions. If your summaries contain HTML with relative image or link paths, they will not be rewritten automatically. Generate absolute URLs for anything you place inside item_description().

Dates, GUIDs and ordering

Three details decide whether downstream tools handle your feed correctly.

  • Timezone-aware dates. With USE_TZ = True, Django stores aware datetimes and the feed generator formats them correctly. Return a real publication datetime from item_pubdate(), not the time the object was last saved, and add item_updateddate() if you want Atom’s updated field.
  • Stable GUIDs. By default, the item’s link is used as its GUID. That is fine as long as URLs never change. If slugs can be edited after publication, define item_guid() to return something permanent, such as a string built from the primary key, and set item_guid_is_permalink = False. Changing GUIDs is a classic cause of items being posted twice by auto-posting tools.
  • Only published items, newest first. Filter out drafts and future-dated items in items(), and order by publication date descending. A draft that leaks into the feed can be picked up and shared within minutes.

Watch out for bulk imports and migrations. If you import hundreds of old articles with their original publication dates, only the newest will appear in the feed, which is usually what you want. But if an import sets every publication date to “now”, the feed suddenly contains twenty items that look brand new, and every connected auto-posting tool will try to share them. Set real historical dates during imports, or pause the automation until the import is finished and verified.

Keep the number of items sensible. Twenty or so recent items is enough for most sites. Very long feeds are slow to generate and fetch, while very short ones can cause missed items if you publish several at once.

Descriptions, templates and full content

The item_description() method controls the text that appears in each item. For many sites a plain summary works best: auto-posting tools often use the title and the start of the description to build the social post, and a clean, readable summary produces better posts than a block of HTML.

If you prefer templates, set description_template (and optionally title_template) on the feed class. Django renders the template for each item with the object available as obj. This is handy for including an image tag, a “read more” link or a formatted date. Remember that the rendered HTML is escaped into the description element, so keep it simple and valid.

Some sites want full content in the feed for readers. You can add extra elements by subclassing the feed generator, as shown below, for example to output content:encoded with the full article while keeping a short summary in description.

Images and enclosures

Social posts without images get far less attention, so it helps if your feed makes a good image easy to find. There are three common approaches:

  1. Open Graph tags on the article page. Many auto-posting tools look at the linked page’s og:image tag. If your article template already outputs good Open Graph tags with absolute image URLs, you may not need anything in the feed itself.
  2. Enclosures. The framework supports item_enclosure_url(), item_enclosure_length() e item_enclosure_mime_type(). An enclosure with the image URL, its size in bytes and a type such as image/jpeg is a clear signal for feed consumers.
  3. An image in the description. An absolute <img> at the start of the description is understood by many readers and tools.

For more control, you can add the Media RSS namespace by subclassing Rss201rev2Feed from django.utils.feedgenerator, overriding rss_attributes() to declare the namespace and add_item_elements() to write a media:content element, then setting feed_type on your feed class to the new generator. Pass the extra data through item_extra_kwargs().

Atom, categories and multiple feeds

To publish Atom instead of RSS, import Atom1Feed from django.utils.feedgenerator and set feed_type = Atom1Feed. A common pattern is to subclass your RSS feed and change only the feed type and subtitle, then expose both under different URLs.

Categories are available through item_categories(), which returns a list of strings. Many auto-posting tools can turn categories into hashtags or use them for filtering, so returning meaningful tags is worthwhile.

You can also create feeds with parameters, for example one feed per category. Define get_object() to load the category from the URL arguments, and use the object in items(), title() e link(). That lets you send different topics to different channels from one codebase.

Finally, make the feed discoverable by adding a link element to your base template’s head: <link rel="alternate" type="application/rss+xml" title="Company news" href="/news/feed/">, ideally generating the path with the url template tag so it follows your URLconf. Browsers, readers and tools use it to find the feed from any page.

Performance, caching and testing

Feeds are fetched often, sometimes every few minutes by several services. Generating the feed on every request is usually cheap, but on busy sites it is worth caching. Wrapping the feed view with Django’s cache_page decorator in the URLconf for a few minutes keeps the load down while still delivering new items quickly. Avoid very long cache times, or new posts will be delayed for every consumer.

Test the output before you connect anything to it:

  • Fetch the feed with curl and confirm it returns status 200 and an XML content type.
  • Check that every link and image URL is absolute and uses your real domain with https.
  • Run the feed through a validator such as the W3C Feed Validation Service.
  • Write a small test with Django’s test client that requests the feed and asserts that published items appear and drafts do not.

The official Django syndication framework documentation covers every hook in detail and is worth keeping open while you build.

Connecting the feed to PostRSS

Once the feed is live, PostRSS can use it as a source like any other RSS or Atom feed. It checks the feed every 5 minutes (every minute on Enterprise plans) and publishes each new item with its image and link to the networks you connect; the features page lists 66, from Facebook Pages, X and LinkedIn to Telegram, Mastodon, Bluesky and team chats. The image comes from the feed item or from the page’s Open Graph tags.

For developers, PostRSS also offers a REST API v1 and outgoing webhooks, so a Django application can create targets or read reports from its own code if needed. Keyword filters, hashtags from categories and UTM parameters are set per source. See the PostRSS features page for the full list.

Related reading

The bottom line

Django’s syndication framework gives any Django site a proper feed with very little code. Subclass Feed, return only published items newest first, set the real domain so links are absolute, keep GUIDs stable, provide a good image and cache lightly. Validate the result once, add an autodiscovery link, and your custom site becomes a source that readers and automation tools can follow reliably.

FAQ

Does Django have built-in RSS support?

Yes. The django.contrib.syndication framework ships with Django and generates RSS 2.0 and Atom feeds from a Python class. You do not need a third-party package for a standard feed.

Why do the links in my Django feed point to example.com?

The sites framework is installed and the Site record still contains the default domain. Update the domain for your SITE_ID to your real domain, and the feed will use it for absolute links.

How do I add images to a Django RSS feed?

Use the enclosure methods on the feed class, put an absolute image tag in the description, or add Media RSS elements with a custom feed generator. Make sure the article page also has an Open Graph image, since many tools read it.

How many items should a Django feed include?

Around twenty recent items suits most sites. It keeps the feed fast while giving tools enough history to catch up if several items are published close together.

Can I create separate feeds per category in Django?

Yes. Define get_object() to read the category from the URL, and use it to filter items() and set the title and link. Each category then has its own feed URL for readers or auto-posting.

New guides, once a month

What changed in the networks, what broke, and how to fix it before it costs you reach.

We send a confirmation e-mail first. Unsubscribe any time.
PostRSS - Automação de feeds RSS e postagem automática
Visão Geral de Privacidade

Este site utiliza cookies para que possamos proporcionar a melhor experiência de usuário possível. As informações de cookies são armazenadas no seu navegador e desempenham funções como reconhecê-lo ao retornar ao nosso site e ajudar nossa equipe a entender quais seções do site você considera mais interessantes e úteis.