annotate news/models.py @ 1055:6ce40d6f39de

Use icon for home link. Don't depend on external site for placeholder images.
author Brian Neal <bgneal@gmail.com>
date Thu, 17 Mar 2016 19:45:35 -0500
parents 9fc12bbc8c81
children
rev   line source
gremmie@1 1 """
gremmie@1 2 Models for the news application.
gremmie@1 3 """
bgneal@997 4 import datetime
gremmie@1 5
bgneal@1002 6 from django.core.urlresolvers import reverse
gremmie@1 7 from django.db import models
bgneal@49 8 from django.contrib.auth.models import User
gremmie@1 9 from tagging.fields import TagField
gremmie@1 10
bgneal@997 11 from core.markup import site_markup
bgneal@997 12
bgneal@997 13
bgneal@997 14 # News App versions
bgneal@997 15 NEWS_VERSION = 2
bgneal@997 16
gremmie@1 17
gremmie@1 18 class Category(models.Model):
bgneal@54 19 """News stories belong to categories"""
bgneal@240 20 title = models.CharField(max_length=64)
bgneal@240 21 slug = models.SlugField(max_length=64)
bgneal@54 22 icon = models.ImageField(upload_to='news/categories/', blank=True)
bgneal@1001 23 forum_slug = models.CharField(
bgneal@1001 24 max_length=80,
bgneal@1001 25 default='',
bgneal@1001 26 blank=True,
bgneal@1001 27 help_text=("Identifies the forum to create comment threads in for "
bgneal@1001 28 "stories in this category. If blank, no comment threads "
bgneal@1001 29 "will be created for stories in this category."))
gremmie@1 30
bgneal@54 31 def __unicode__(self):
bgneal@54 32 return self.title
gremmie@1 33
bgneal@54 34 def num_stories(self):
bgneal@987 35 return Story.objects.filter(category=self.pk).count()
gremmie@1 36
bgneal@54 37 class Meta:
bgneal@54 38 verbose_name_plural = 'Categories'
bgneal@54 39 ordering = ('title', )
gremmie@1 40
gremmie@1 41
bgneal@204 42 class StoryBase(models.Model):
bgneal@204 43 """Abstract model to collect common fields."""
bgneal@54 44 title = models.CharField(max_length=255)
bgneal@54 45 submitter = models.ForeignKey(User)
bgneal@54 46 category = models.ForeignKey(Category)
bgneal@999 47 short_text = models.TextField(default='', blank=True)
bgneal@998 48 long_text = models.TextField(default='', blank=True)
bgneal@204 49 date_submitted = models.DateTimeField(db_index=True)
bgneal@54 50 allow_comments = models.BooleanField(default=True)
bgneal@54 51 tags = TagField()
bgneal@218 52 front_page_expiration = models.DateField(null=True, blank=True)
bgneal@277 53 update_date = models.DateTimeField(db_index=True, blank=True)
bgneal@462 54 priority = models.IntegerField(db_index=True, default=0, blank=True)
bgneal@486 55 meta_description = models.TextField(blank=True)
bgneal@1005 56 short_markup = models.TextField(default='', blank=True)
bgneal@997 57 long_markup = models.TextField(default='', blank=True)
bgneal@997 58 admin_content = models.TextField(default='', blank=True)
bgneal@997 59 version = models.SmallIntegerField(default=NEWS_VERSION)
gremmie@1 60
bgneal@204 61 class Meta:
bgneal@204 62 abstract = True
bgneal@204 63
bgneal@182 64 def save(self, *args, **kwargs):
bgneal@204 65 if not self.pk:
bgneal@997 66 self.date_submitted = datetime.datetime.now()
bgneal@277 67 self.update_date = self.date_submitted
bgneal@277 68 else:
bgneal@277 69 self.update_date = datetime.datetime.now()
bgneal@204 70
bgneal@1000 71 if self.version >= 2:
bgneal@1000 72 self.short_text = kwargs.pop('short_text', '')
bgneal@1000 73 if not self.short_text and self.short_markup:
bgneal@1000 74 self.short_text = site_markup(self.short_markup)
bgneal@997 75
bgneal@1000 76 self.long_text = kwargs.pop('long_text', '')
bgneal@1000 77 if not self.long_text and self.long_markup:
bgneal@1000 78 self.long_text = site_markup(self.long_markup)
bgneal@997 79
bgneal@997 80 super(StoryBase, self).save(*args, **kwargs)
bgneal@997 81
bgneal@997 82
bgneal@997 83 class PendingStory(StoryBase):
bgneal@997 84 """Stories submitted by users are held pending admin approval"""
gremmie@1 85
bgneal@54 86 def __unicode__(self):
bgneal@54 87 return self.title
gremmie@1 88
bgneal@54 89 class Meta:
bgneal@997 90 ordering = ['-date_submitted']
bgneal@54 91 verbose_name_plural = 'Pending Stories'
gremmie@1 92
gremmie@1 93
bgneal@204 94 class Story(StoryBase):
bgneal@54 95 """Model for news stories"""
bgneal@1001 96 forums_topic = models.OneToOneField('forums.Topic', blank=True, null=True,
bgneal@1001 97 on_delete=models.SET_NULL,
bgneal@1001 98 db_index=False,
bgneal@1001 99 help_text="Forum topic used for comments")
gremmie@1 100
bgneal@54 101 def get_absolute_url(self):
bgneal@1002 102 return reverse('news-story', args=[str(self.id)])
gremmie@1 103
bgneal@54 104 def __unicode__(self):
bgneal@54 105 return self.title
gremmie@1 106
bgneal@54 107 class Meta:
bgneal@997 108 ordering = ['-date_submitted']
bgneal@226 109 verbose_name = 'news story'
bgneal@226 110 verbose_name_plural = 'news stories'
gremmie@1 111
bgneal@54 112 def can_comment_on(self):
bgneal@1001 113 # Only used for version 0 stories
bgneal@54 114 now = datetime.datetime.now()
bgneal@204 115 delta = now - self.date_submitted
bgneal@204 116 return self.allow_comments and delta.days < 30
bgneal@220 117
bgneal@1001 118 def forums_comment_count(self):
bgneal@1001 119 """Returns number of comments for V2 news stories."""
bgneal@1001 120 if self.forums_topic:
bgneal@1001 121 return max(0, self.forums_topic.post_count - 1)
bgneal@1001 122 return 0
bgneal@1001 123
bgneal@220 124 def search_title(self):
bgneal@220 125 return self.title
bgneal@220 126
bgneal@220 127 def search_summary(self):
bgneal@220 128 return u"\n".join((self.short_text, self.long_text))
bgneal@484 129
bgneal@484 130 def ogp_tags(self):
bgneal@484 131 """
bgneal@484 132 Returns a dict of Open Graph Protocol meta tags.
bgneal@484 133
bgneal@484 134 """
bgneal@486 135 desc = self.meta_description.strip()
bgneal@486 136 if not desc:
bgneal@486 137 desc = 'News article submitted by %s on %s.' % (
bgneal@486 138 self.submitter.username,
bgneal@486 139 self.date_submitted.strftime('%B %d, %Y'))
bgneal@486 140
bgneal@484 141 return {
bgneal@484 142 'og:title': self.title,
bgneal@484 143 'og:type': 'article',
bgneal@484 144 'og:url': self.get_absolute_url(),
bgneal@484 145 'og:image': self.category.icon.url,
bgneal@486 146 'og:description': desc,
bgneal@484 147 }