Posts Photos Archives About

According to the documentation here:

If link doesn’t return the domain, the syndication framework will insert the domain of the current site, according to your SITE_ID setting

However, I'm trying to generate a feed of magnet: links. The framework doesn't recognize this and attempts to append the SITE_ID, such that the links end up like this (on localhost):


Is there a way to bypass this?


whp said...

This is a bit gnarly, but here's a potential solution if you don't want to give up on the Django framework:

The problem is that the method add_domain is buried deep in a huge method within syndication framework, and I don't see a clean way to override it. Since this method is used for both the feed URL and the feed items, a monkey patch of add_domain would need to consider this.

Django source:

#Steps: 1: Subclass the Feed class you're using and do a copy-paste override of the huge method get_feed

2: Modify the line:

link = add_domain(
    self._get_dynamic_attr('item_link', item),

To something like:

link = self._get_dynamic_attr('item_link', item)
whp said...

Here's a way to do it with monkey patching, much cleaner.

I like to create a separate folder "django_patches" for these kinds of things:


from django.contrib.syndication import views
from django.contrib.syndication.views import add_domain

def add_domain_if_we_should(domain, url, secure=False):
    if url.startswith('magnet:'):
        return url
        return add_domain(domain, url, secure=False)

views.add_domain = add_domain_if_we_should

Next, add it to your INSTALLED_APPS so that you can patch the function.

Roy Tang said...

I did end up digging through the syndication source code and finding no easy way to override it and did some hacky monkey patching. (Unfortunately I did it before I saw the answers posted here, all of which I assume will work about as well as this one)

Here's how I did it:

def item_link(self, item):
    # adding http:// means the internal get_feed won't modify it
    return "http://"+item.magnet_link

def get_feed(self, obj, request):
    # hacky way to bypass the domain handling
    feed = super().get_feed(obj, request)
    for item in feed.items:
        # strip that http:// we added above
        item['link'] = item['link'][7:]
    return feed

For future readers, this was as of Django 2.0.1. Hopefully in a future patch they allow support for protocols like magnet.