Search code examples
pythondjangorssrss-readerrss2

Django Rss Feed add image to description


I am trying to use Django rss feeds to view feeds on rss viewer app.

i used from django.contrib.syndication.views import Feed to create rss feeds

but it only had 3 fields title, description and link i added custom fields by using from django.utils.feedgenerator import Rss201rev2Feed

and it generates the extra fields with no issues

enter image description here

but when i open it with a rss viewer it doesn't show those extra fields or the image

enter image description here

My question is how can i make those extra fields show up in app ?

does it not show up because app only shows title, description and link and those other fields are not processed ?

so how can i embed image and other fields in description so it shows up (most importantly image show up) ?

i have went over documentation many times can't seem to get it right.

here is the view code from Django app

class CustomFeedGenerator(Rss201rev2Feed):
    def add_item_elements(self, handler, item):
        super(CustomFeedGenerator, self).add_item_elements(handler, item)
        handler.addQuickElement(u"image", item['image'])
        handler.addQuickElement(u"seller_name", item['seller_name'])
        handler.addQuickElement(u"price", item['price'])

class LatestPostsFeed(Feed):
    title = "www.marktplaats.nl"
    link = "/feeds/"
    description = "Updates on changes and additions to posts published in the starter."

    feed_type = CustomFeedGenerator

    def items(self):
        return Check_Ads_One.objects.order_by('title')[:5]

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

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

    def item_link(self, item):
        return item.prod_link

    def item_extra_kwargs(self, item):

        return { 'image': item.image_link,
                'seller_name' : item.seller_name,
                'price': item.price,}

I'm using Rss Savvy for the reader app


Solution

  • <image></image> is not a standard element of Items as per RSS Specification stated here. But it is a valid element of channel. Anyway, there are several ways you can add image to feed. Like:

    Using enclosures

    As stated here, you can use enclosures to add image in feed. Django Feed Framework also provides add_enclosures() function which we can use. Here are two possible solutions based on that:

    First Solution (Image Stored in Django)

    I am assuming you have an image field in the model like this:

    class Check_Ads_One(models.Model):
       image = models.ImageField()
    

    Then update the LatestPostsFeed class like this:

    class LatestPostsFeed(Feed):
        title = "www.marktplaats.nl"
        link = "/feeds/"
        description = "Updates on changes and additions to posts published in the starter."
    
        feed_type = feedgenerator.Rss201rev2Feed
    
        # Rest of the code
    
        def get_object(self, request, *args, **kwargs):
            self.request = request
            return super(LatestPostsFeed, self).get_object(request, *args, **kwargs) 
    
        def get_image_url(self, url):
            return self.request.build_absolute_uri('/media{}'.format(url))
    
        def item_enclosures(self, item):
            return [feedgenerator.Enclosure(self.get_image_url(item.image.url), str(item.image.size), 'image/{}'.format(item.image.name.split('.')[-1]))]
    
     
    

    Second Solution (Image not Stored in Django)

    If you are storing the links of image instead of actual image, then use the following approach:

    import urllib
    
    class LatestPostsFeed(Feed):
        title = "www.marktplaats.nl"
        link = "/feeds/"
        description = "Updates on changes and additions to posts published in the starter."
    
        feed_type = feedgenerator.Rss201rev2Feed
    
        # Rest of the code
    
        def get_size_and_type_of_image(self, image_url):
           # This method can be moved to models.py, and on save of `Check_Ads_One` it will calculate the size and type of image from url and store in DB. Then it will much optimized solution
           data = urllib.urlopen(image_url)
           return data['Content-Length'], data['Content-Type']
    
        def item_enclosures(self, item):
            content_length, content_type = self.get_size_and_type_of_image(item.image)
            return [feedgenerator.Enclosure(item.image, content_length, content_type)]
    

    Image information in CDATA(alternative solution)

    You can add CDATA tag in description and add image there:

    def item_description(self, item):
        return '<![CDATA[\n{} <img src="{}" alt="{}">\n]>'.format(item.paragraph, item.image, item.title)
    

    More information can be found in this StackOverflow Answer