Package zinnia :: Module models
[hide private]

Source Code for Module zinnia.models

  1  """Models of Zinnia""" 
  2  import warnings 
  3  from datetime import datetime 
  4   
  5  from django.db import models 
  6  from django.db.models import Q 
  7  from django.utils.html import strip_tags 
  8  from django.utils.html import linebreaks 
  9  from django.contrib.auth.models import User 
 10  from django.contrib.sites.models import Site 
 11  from django.db.models.signals import post_save 
 12  from django.utils.importlib import import_module 
 13  from django.contrib.comments.models import Comment 
 14  from django.contrib.comments.models import CommentFlag 
 15  from django.contrib.comments.moderation import moderator 
 16  from django.utils.translation import ugettext_lazy as _ 
 17   
 18  import mptt 
 19  from tagging.fields import TagField 
 20   
 21  from zinnia.settings import USE_BITLY 
 22  from zinnia.settings import UPLOAD_TO 
 23  from zinnia.settings import ENTRY_TEMPLATES 
 24  from zinnia.settings import ENTRY_BASE_MODEL 
 25  from zinnia.managers import entries_published 
 26  from zinnia.managers import EntryPublishedManager 
 27  from zinnia.managers import AuthorPublishedManager 
 28  from zinnia.managers import DRAFT, HIDDEN, PUBLISHED 
 29  from zinnia.moderator import EntryCommentModerator 
 30  from zinnia.signals import ping_directories_handler 
 31  from zinnia.signals import ping_external_urls_handler 
32 33 34 -class Author(User):
35 """Proxy Model around User""" 36 37 objects = models.Manager() 38 published = AuthorPublishedManager() 39
40 - def entries_published_set(self):
41 """Return only the entries published""" 42 return entries_published(self.entry_set)
43 44 @models.permalink
45 - def get_absolute_url(self):
46 """Return author's URL""" 47 return ('zinnia_author_detail', (self.username,))
48
49 - class Meta:
50 """Author's Meta""" 51 proxy = True
52
53 54 -class Category(models.Model):
55 """Category object for Entry""" 56 57 title = models.CharField(_('title'), max_length=255) 58 slug = models.SlugField(help_text=_('used for publication'), 59 unique=True, max_length=255) 60 description = models.TextField(_('description'), blank=True) 61 62 parent = models.ForeignKey('self', null=True, blank=True, 63 verbose_name=_('parent category'), 64 related_name='children') 65
66 - def entries_published_set(self):
67 """Return only the entries published""" 68 return entries_published(self.entry_set)
69 70 @property
71 - def tree_path(self):
72 """Return category's tree path, by his ancestors""" 73 if self.parent: 74 return '%s/%s' % (self.parent.tree_path, self.slug) 75 return self.slug
76
77 - def __unicode__(self):
78 return self.title
79 80 @models.permalink
81 - def get_absolute_url(self):
82 """Return category's URL""" 83 return ('zinnia_category_detail', (self.tree_path,))
84
85 - class Meta:
86 """Category's Meta""" 87 ordering = ['title'] 88 verbose_name = _('category') 89 verbose_name_plural = _('categories')
90
91 92 -class EntryAbstractClass(models.Model):
93 """Base Model design for publishing entries""" 94 STATUS_CHOICES = ((DRAFT, _('draft')), 95 (HIDDEN, _('hidden')), 96 (PUBLISHED, _('published'))) 97 98 title = models.CharField(_('title'), max_length=255) 99 100 image = models.ImageField(_('image'), upload_to=UPLOAD_TO, 101 blank=True, help_text=_('used for illustration')) 102 content = models.TextField(_('content')) 103 excerpt = models.TextField(_('excerpt'), blank=True, 104 help_text=_('optional element')) 105 106 tags = TagField(_('tags')) 107 categories = models.ManyToManyField(Category, verbose_name=_('categories'), 108 blank=True, null=True) 109 related = models.ManyToManyField('self', verbose_name=_('related entries'), 110 blank=True, null=True) 111 112 slug = models.SlugField(help_text=_('used for publication'), 113 unique_for_date='creation_date', 114 max_length=255) 115 116 authors = models.ManyToManyField(User, verbose_name=_('authors'), 117 blank=True, null=False) 118 status = models.IntegerField(choices=STATUS_CHOICES, default=DRAFT) 119 featured = models.BooleanField(_('featured'), default=False) 120 comment_enabled = models.BooleanField(_('comment enabled'), default=True) 121 pingback_enabled = models.BooleanField(_('linkback enabled'), default=True) 122 123 creation_date = models.DateTimeField(_('creation date'), default=datetime.now) 124 last_update = models.DateTimeField(_('last update'), default=datetime.now) 125 start_publication = models.DateTimeField(_('start publication'), 126 help_text=_('date start publish'), 127 default=datetime.now) 128 end_publication = models.DateTimeField(_('end publication'), 129 help_text=_('date end publish'), 130 default=datetime(2042, 3, 15)) 131 132 sites = models.ManyToManyField(Site, verbose_name=_('sites publication')) 133 134 login_required = models.BooleanField(_('login required'), default=False, 135 help_text=_('only authenticated users can view the entry')) 136 password = models.CharField(_('password'), max_length=50, blank=True, 137 help_text=_('protect the entry with a password')) 138 139 template = models.CharField(_('template'), max_length=250, 140 default='zinnia/entry_detail.html', 141 choices=[('zinnia/entry_detail.html', 142 _('Default template'))] + 143 ENTRY_TEMPLATES, 144 help_text=_('template used to display the entry')) 145 146 objects = models.Manager() 147 published = EntryPublishedManager() 148 149 @property
150 - def html_content(self):
151 """Return the content correctly formatted""" 152 if not '</p>' in self.content: 153 return linebreaks(self.content) 154 return self.content
155 156 @property
157 - def previous_entry(self):
158 """Return the previous entry""" 159 entries = Entry.published.filter( 160 creation_date__lt=self.creation_date)[:1] 161 if entries: 162 return entries[0]
163 164 @property
165 - def next_entry(self):
166 """Return the next entry""" 167 entries = Entry.published.filter( 168 creation_date__gt=self.creation_date).order_by('creation_date')[:1] 169 if entries: 170 return entries[0]
171 172 @property
173 - def word_count(self):
174 """Count the words of an entry""" 175 return len(strip_tags(self.html_content).split())
176 177 @property
178 - def is_actual(self):
179 """Check if an entry is within publication period""" 180 now = datetime.now() 181 return now >= self.start_publication and now < self.end_publication
182 183 @property
184 - def is_visible(self):
185 """Check if an entry is visible on site""" 186 return self.is_actual and self.status == PUBLISHED
187 188 @property
189 - def related_published_set(self):
190 """Return only related entries published""" 191 return entries_published(self.related)
192 193 @property
194 - def discussions(self):
195 """Return published discussions""" 196 return Comment.objects.for_model(self).filter(is_public=True)
197 198 @property
199 - def comments(self):
200 """Return published comments""" 201 return self.discussions.filter(Q(flags=None) | Q( 202 flags__flag=CommentFlag.MODERATOR_APPROVAL))
203 204 @property
205 - def pingbacks(self):
206 """Return published pingbacks""" 207 return self.discussions.filter(flags__flag='pingback')
208 209 @property
210 - def trackbacks(self):
211 """Return published trackbacks""" 212 return self.discussions.filter(flags__flag='trackback')
213 214 @property
215 - def short_url(self):
216 """Return the entry's short url""" 217 if not USE_BITLY: 218 return False 219 220 from django_bitly.models import Bittle 221 222 bittle = Bittle.objects.bitlify(self) 223 url = bittle and bittle.shortUrl or self.get_absolute_url() 224 return url
225
226 - def __unicode__(self):
227 return '%s: %s' % (self.title, self.get_status_display())
228 229 @models.permalink
230 - def get_absolute_url(self):
231 """Return entry's URL""" 232 return ('zinnia_entry_detail', (), { 233 'year': self.creation_date.strftime('%Y'), 234 'month': self.creation_date.strftime('%m'), 235 'day': self.creation_date.strftime('%d'), 236 'slug': self.slug})
237
238 - class Meta:
239 abstract = True
240
241 242 -def get_base_model():
243 """Determine the base Model to inherit in the 244 Entry Model, this allow to overload it.""" 245 if not ENTRY_BASE_MODEL: 246 return EntryAbstractClass 247 248 dot = ENTRY_BASE_MODEL.rindex('.') 249 module_name, class_name = ENTRY_BASE_MODEL[:dot], ENTRY_BASE_MODEL[dot + 1:] 250 try: 251 _class = getattr(import_module(module_name), class_name) 252 return _class 253 except (ImportError, AttributeError): 254 warnings.warn('%s cannot be imported' % ENTRY_BASE_MODEL, RuntimeWarning) 255 return EntryAbstractClass
256
257 258 -class Entry(get_base_model()):
259 """Final Entry model""" 260
261 - class Meta:
262 """Entry's Meta""" 263 ordering = ['-creation_date'] 264 verbose_name = _('entry') 265 verbose_name_plural = _('entries') 266 permissions = (('can_view_all', 'Can view all'), 267 ('can_change_author', 'Can change author'), )
268 269 270 moderator.register(Entry, EntryCommentModerator) 271 mptt.register(Category, order_insertion_by=['title']) 272 post_save.connect(ping_directories_handler, sender=Entry, 273 dispatch_uid='zinnia.entry.post_save.ping_directories') 274 post_save.connect(ping_external_urls_handler, sender=Entry, 275 dispatch_uid='zinnia.entry.post_save.ping_external_urls') 276