I have an application with entries and containers. There is a ManyToMany relationship between them:
- A container contains 0 or more entries
- An entry is in 0 or more containers
I use the following schema for URIs:
- prefix/container
- prefix/container/entry
This means that several URLs can lead to the same entry. Each URL defines a different context.
I’m trying to create a RSS/Atom Feed for each container. My issue is how to implement the Feed.item_link method to returns
the right URL. I need to invoke urlresolvers.reverse with two arguments: the container identifier and the entry identifier.
Unfortunately item_link receives only the entry as parameter. Only Feed.get_object method knows about the container. What is the cleanest solution to solve this issue ?
Sample code follows:
Models
class Entry(models.Model):
pass
class Container(models.Model):
entries = models.ManyToManyField("Entries",
related_name='containers',
null=True,
blank=True
)
URLs
url(r'^prefix/(?P<container_slug>[-\w]+)/rss$', feeds.LatestEntries()),
Feed
class LatestEntries(Feed):
title = "foo"
description = "bar"
def get_object(self, request, container_slug):
return get_object_or_404(models.Container, slug=container_slug)
def item_link(self, entry):
# TODO: How to pass container_slug to reverse() ?
return urlresolvers.reverse('up.views.portfolio_image', kwargs={
'container_slug': 'FIXME',
'entry_slug': entry.slug,
})
With syndication the situation is complicated by the fact that a single instance of
Feedis used to handle all requests, therefore you can’t reliably store the value as an attribute of theFeedinstance, instead, you have to somehow use the objects you create to pass the value forward. I can only think of one way forward in this case, short of reimplementing the wholeFeedclass yourself.You’ll need to attach the argument to the object returned by
get_object, for example like this (although this step seems redundant in this case as yourContainerinstances will contain this as a regular model field already):Then, in
items, you’ll have to take this value from the container instance and attach it to each item returned, for example:You can avoid enumerating the queryset in this step by using a closure and a generator for the list of entries if you feel like it, although it shouldn’t matter in this case if you’re only returning a handful of entries.
Then, finally, you can implement
item_linklike this: