0

I'd like to cache only the comments section of each article without caching the whole page, so the article views, I have

try:
    cmnts_key = post_slug
    comments = cache.get(cmnts_key)
    if not comments:
        comments = Comment.objects.filter(post=post).order_by("created")
        cache.set(cmnts_key, comments, COMMENTS_CACHE_TIMEOUT)
except: 
    print 'comments fetch exception'
    pass

...
args = {}
args['post'] = post
args['comments'] = comments
return render(request, "post.html", args)

However in the template where it tries to render comments {% for comment in comments %} I get:

'Article' object is not iterable.

I don't know whether it is principally impossible to iterate over cached query set results or there is a problem is my code, and if so, how can I fix it?

UPDATE. Here is my comment model:

class Comment(models.Model):
    author = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, default='', blank=True)
    body = models.TextField()
    post = models.ForeignKey(Article)
    published = models.BooleanField(default=True)


    def __unicode__(self):
        return unicode("%s: %s" % (self.post, self.body[:60]))

    def get_absolute_url(self):
        return "/article/"+ self.slug     

    def save(self, *args, **kwargs):
        self.title = comment_truncate(self.body)        
        super(Comment, self).save(*args, **kwargs)

    @property
    def cache_key(self):
        return self.get_absolute_url()
Jand
  • 2,527
  • 12
  • 36
  • 66
  • Will probably need to see more code. – C.B. Nov 25 '15 at 19:08
  • @C.B I think I've mentioned the problematic code. The views work perfecly well without the cache. What do you think is missing? – Jand Nov 25 '15 at 19:20
  • 1
    If you are actually specifying that the context variable `comments` points to your comments queryset. Right now, it looks like your comments context variable is pointing to an article object, not a comments queryset. – C.B. Nov 25 '15 at 19:21
  • can you paste the comment model? – Navid777 Nov 25 '15 at 19:26
  • @Navid777 I updated with the comment model. – Jand Nov 25 '15 at 19:32
  • the problem is possibly from the `__unicode__` method of the `Article` model, can you paste the `Article` model's `__unicode__` ? – Navid777 Nov 25 '15 at 19:35
  • @Navid777 sure, here it is : `def __unicode__(self): return unicode(self.title)` – Jand Nov 25 '15 at 19:37
  • in `__unicode__` of comment change the `self.post` to `self.post.__unicode__() ` and see if that fixes the problem. – Navid777 Nov 25 '15 at 19:41
  • @Navid, the problem does not occure at comment save, but rather on article GET request. So I don't see what it has to do with model methods. I guess you are on the wrong track. – Jand Nov 25 '15 at 19:43

1 Answers1

1

You seem to be using the article slug as the key to get/set the comments in the cache. I guess that elsewhere, in code you haven't shown, you're using that same key to cache an actual Article (which would make sense), and that's what you're retrieving in this code.

You might want to disambiguate them by using "comments:%s" % post_slug as the cache key.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Well spotted as ever. You are a legend Daniel. Just wondering security/performance-wise does it make any sense to used a hashed key instead of using "comments:%s" % post_slug as hash key? – Jand Nov 25 '15 at 20:54
  • I shouldn't think so. Caches are generally key-value stores, they'll take care of storing the key in the most efficient way. – Daniel Roseman Nov 25 '15 at 20:56
  • Alright, also I appreciate if you see this (somehow) relevant question: http://stackoverflow.com/questions/33749369/how-to-invalidate-cache-page-in-django – Jand Nov 25 '15 at 22:16