class Tag(models.Model): blog = models.ForeignKey("Blog") name = models.CharField("Tag name", max_length=100) slug = models.SlugField(max_length=100, db_index=True) template = models.CharField("Template", max_length=100, blank=True) count = models.IntegerField(default=0, editable=False) description = MarkupField(default="", blank=True, renderer=render) def get_summary(self): if self.description_summary_html: return self.description_summary_html else: return self.description_html def decrement(self): count = self.count if count: count -= 1 self.count = count return count def increment(self): self.count += 1 return self.count def __unicode__(self): return "%s (in %s)" % (self.name, self.blog) def posts(self): now = datetime.datetime.now() posts = self.post_set.filter( published=True, display_time__lte=now, version="live", ).order_by('-display_time') return posts @models.permalink def get_absolute_url(self): return ("blog_tag", (), dict(blog_slug=self.blog.slug, tag_slug=self.slug)) def get_blog_relative_url(self): return "tag/%s/" % self.slug def get_feed(self): import feeds title = "RSS Feed for %s posts in %s" % (self.name, self.blog.title) url = feeds.BlogTagFeed.get_url(self) return dict(title=title, url=url)
class Comment(models.Model): objects = CommentManager() content_type = models.ForeignKey(ContentType, db_index=True) object_id = models.PositiveIntegerField(db_index=True) content_object = generic.GenericForeignKey('content_type', 'object_id') visible = models.BooleanField(default=False) moderated = models.BooleanField(default=False) created_time = models.DateTimeField(auto_now_add=True) type = models.CharField("Type of comment", max_length=100, blank=True) owner = models.ForeignKey(User, blank=True, null=True, default=None) group = models.CharField("Optional comment group", max_length=100, blank=True, default="") name = models.CharField("Author's name", max_length=100) email = models.EmailField("Author's email", blank=True) url = models.CharField(blank=True, default="", max_length=255) content = MarkupField(default="", renderer=_comment_renderer) def __unicode__(self): return self.name def serialize(self): return { "visible": self.visible, "moderated": self.moderated, "name": self.name, "email": self.email, "url": self.url, "markup": self.content_markup_type.split('_', 1)[-1], "content_source": self.content, "content": self.content_html, "created_time": self.created_time.ctime() } def site_link(self): object_url = self.object_url() + '#comment' + str(self.id) url = '''<a href="%s">comment by %s</a>''' % (object_url, self.name) return url site_link.allow_tags = True def object_url(self): return self.content_object.get_absolute_url() def comment_object_description(self): return unicode(self.content_object)
class Author(models.Model): user = models.ForeignKey(User) bio = MarkupField(default="", blank=True, renderer=render)
class Post(models.Model): blog = models.ForeignKey(Blog) title = models.CharField("Post Title", max_length=100) slug = models.SlugField("Post Slug", max_length=100, db_index=True) published = models.BooleanField("Published?", default=False) guid = models.CharField(max_length=255, blank=True) allow_comments = models.BooleanField("Allow Comments?", default=True) show_comments = models.BooleanField("Show Comments?", default=True) series = models.CharField("Series name", max_length=100, blank=True, default="") source = models.CharField("Post source", max_length=100, blank=True, default="") created_time = models.DateTimeField(auto_now_add=True) edit_time = models.DateTimeField(auto_now=True) display_time = models.DateTimeField("Display Time", default=datetime.datetime.now) tags = models.ManyToManyField("Tag", blank=True) tags_text = models.TextField("Comma separated tags", default="", blank=True) content = MarkupField(default="", renderer=render, blank=True) version = models.CharField("Version", max_length=100, default="live") version_id = models.IntegerField("Parent Post ID", blank=True, null=True) template_path = models.CharField("Template path (blank for default)", max_length=100, default="", blank=True) #created_time = models.DateTimeField(auto_now_add=True) objects = models.Manager() published_posts = PublisedPostManager() def get_tags(self): return self.tags.filter(count__gt=0) def get_template_names(self, name="default"): templates = [] if self.template_path: templates.append(os.path.join(self.template_path, name)) templates.append(os.path.join("blog/posts/", name)) return templates def is_series(self): return bool(self.series) def get_series(self): posts = Post.objects.filter( series=self.series).order_by('display_time') index_posts = [(i + 1, post) for i, post in enumerate(posts)] current_part = None for i, post in index_posts: if post is self: current_part = i break return index_posts, current_part def get_summary(self): if self.content_summary_html: return self.content_summary_html else: return self.content_html def get_admin_abbrev(self): if len(self.content_text) < 100: return self.content_text return self.content_text[:100] + " [...]" get_admin_abbrev.short_description = "Content (abbreviated)" def get_admin_html(self): return self.html get_admin_html.allow_tags = True def __unicode__(self): if self.version == 'live': return self.title return "%s [%s]" % (self.title, self.version.upper()) def date_url(self): year = self.display_time.year month = self.display_time.month day = self.display_time.day return "%d/%d/%d/%s" % (year, month, day, self.slug) @models.permalink def get_absolute_url(self): blog_slug = self.blog.slug slug = self.slug if '|' in slug: slug = slug.split('|', 1)[-1] year = self.display_time.year month = self.display_time.month day = self.display_time.day return ("blog_post", (), dict(blog_slug=blog_slug, year=year, month=month, day=day, slug=slug)) def get_blog_relative_url(self): year = self.display_time.year month = self.display_time.month day = self.display_time.day return "%i/%i/%i/%s/" % (year, month, day, self.slug) def _remove_tags(self): if self.pk is not None: if self.version != 'live': return tags = Tag.objects.filter(blog=self.blog, post=self) for tag in self.tags.all(): tag.decrement() tag.save() self.tags.remove(tag) def _add_tags(self): """Creates tags or increments tag counts as neccesary. """ if self.version != 'live': return tags = [t.strip() for t in self.tags_text.split(',')] tags = list(set(tags)) for tag_name in tags: tag_slug = slugify(tag_name) if tag_slug: try: tag = Tag.objects.get(blog=self.blog, slug=tag_slug) except Tag.DoesNotExist: tag = Tag(blog=self.blog, name=tag_name, slug=tag_slug) tag.increment() tag.save() self.tags.add(tag) def delete(self, *args, **kwargs): self._remove_tags() super(Post, self).delete(*args, **kwargs) def save(self, *args, **kwargs): self._remove_tags() super(Post, self).save(*args, **kwargs) self._add_tags() if self.version == 'live' and self.published: broadcast.safe_first.new_content_on_site() def get_tags(self): tags = list(self.tags.all()) tags.sort(key=lambda t: t.name.lower()) return tags def is_new(self): age = datetime.datetime.now() - self.display_time return age.days < 7 def get_parent_version(self): if self.version_id is None: return self parent_post = Post.objects.get(self.version_id) return parent_post def get_version(self, version): """Creates a draft post that can be used for previews.""" if self.version == version: return self #version_slug = self.get_version_slug(version) parent_version_id = self.get_parent_version().id try: versioned_post = Post.objects.get(blog=self.blog, version_id=parent_version_id, version=version) return versioned_post except Post.DoesNotExist: versioned_post = Post(version_id=parent_version_id, published=False, blog=self.blog, version=version) versioned_post.save() copy_attribs = [ 'title', 'tags_text', 'content', 'content_markup_type', 'allow_comments', 'published', 'display_time', 'slug' ] for attrib in copy_attribs: setattr(versioned_post, attrib, getattr(self, attrib)) versioned_post.save() return versioned_post def delete_version(self, version): """Removes the draft object associated with a post.""" parent_version_id = self.get_parent_version().id try: versioned_post = Post.objects.get(blog=self.blog, version_id=parent_version_id, version=version) versioned_post.delete() except Post.DoesNotExist: pass def version_exists(self, version): parent_version_id = self.get_parent_version().id try: versioned_post = Post.objects.get(blog=self.blog, version_id=parent_version_id, version=version) return True except Post.DoesNotExist: return False def get_related_posts(self, count=10): post = self if post.version != "live": slug = self.slug.split('|', 1)[-1] try: post = Post.objects.get(slug=slug, version="live") except Post.DoesNotExist: pass blog = post.blog tags = list(post.tags.all()) posts = Post.objects.filter( blog=blog, tags__in=tags).exclude(pk=post.id).order_by('-display_time')[:1000] def count_iter(i): return sum(1 for _ in i) counts_and_posts = [(post, count_iter(similar_posts)) for post, similar_posts in groupby(posts)] if counts_and_posts: max_count = max(counts_and_posts, key=lambda c: c[1])[1] min_count = min(counts_and_posts, key=lambda c: c[1])[1] if min_count != max_count: counts_and_posts = [ cap for cap in counts_and_posts if cap[1] != min_count ] counts_and_posts.sort(key=lambda i: (i[1], i[0].display_time)) return [cp[0] for cp in reversed(counts_and_posts[-count:])]
class Blog(models.Model): owner = models.ForeignKey(User) created_time = models.DateTimeField(auto_now_add=True) title = models.CharField("Title of the Blog", max_length=100) tagline = models.CharField("Tag line", max_length=200, blank=True) slug = models.SlugField(max_length=100, unique=True, db_index=True) posts_per_page = models.IntegerField(default=10) template = models.CharField("Template path", max_length=100) description = MarkupField(default="", renderer=render, blank=True) def get_full_template_name(self, template_name): return self.template.rstrip('/') + '/' + self.template def get_template_names(self, template_name, alternates=None): alternates = alternates or [] alternates = [os.path.join(p, template_name) for p in alternates] templates = [] templates += alternates templates.append(os.path.join('blog', template_name)) return templates def __unicode__(self): return self.title def posts(self): now = datetime.datetime.now() posts = self.post_set.filter( published=True, version="live", display_time__lte=now).order_by("-display_time") return posts def get_tag(self, tag_slug): return Tag.objects.get(blog=self, slug=tag_slug) def tags(self): return self.tag_set.all().order_by("-count") @models.permalink def get_absolute_url(self): blog_slug = self.slug return ("blog_front", (), dict(blog_slug=blog_slug)) def get_tag_cloud(self, tag_count=30): return TagCloud(self, max_tags=tag_count) def get_feed(self): import feeds title = "%s RSS Feed" % self.title url = feeds.BlogFeed.get_url(self) return dict(title=title, url=url)
class Channel(models.Model): template = models.CharField("Template", max_length=100, blank=True) title = models.CharField("Channel Title", max_length=100) tagline = models.CharField("Tag line", max_length=200) slug = models.SlugField(max_length=100, db_index=True) posts_per_page = models.IntegerField(default=10) template = models.CharField("Template prefix", max_length=100, blank=True) description = MarkupField(default="", renderer=render, blank=True) blogs = models.ManyToManyField("Blog") def is_channel(self): """ Returns True if this is a channel (for the benefit of tempalates) """ return True def child_blogs(self): return list(self.blogs.order_by('title')) def get_full_template_name(self, template_name): return self.template.rstrip('/') + '/' + self.template def get_template_names(self, template_name): template_prefix = self.template.rstrip('/') return [ template_prefix + '/' + template_name, 'theme/' + template_name, template_name ] def __unicode__(self): return self.title def posts(self): now = datetime.datetime.now() posts = Post.objects.filter( blog__in=self.blogs.all(), published=True, version="live", display_time__lte=now).order_by("-display_time") return posts def get_tag(self, tag_slug): channel_tag = ChannelTag(self.slug, tag_slug) return channel_tag def tags(self): tags = [] for blog in self.blogs.all(): tags += list(blog.tags()) tags.sort(key=lambda t: t.slug) collated_tags = [] for tag_slug, similar_tags in groupby(tags, lambda t: t.slug): similar_tags = list(similar_tags) channel_tag = ChannelTag(self.slug, tag_slug) channel_tag.slug = tag_slug channel_tag.name = similar_tags[0].name channel_tag.description = similar_tags[0].description channel_tag.count = sum(tag.count for tag in similar_tags) collated_tags.append(channel_tag) collated_tags.sort(key=lambda t: -t.count) return collated_tags def get_tag_cloud(self, tag_count=30): return TagCloud(self, max_tags=tag_count) @models.permalink def get_absolute_url(self): channel_slug = self.slug return ("blog_front", (), dict(blog_slug=channel_slug)) def get_feed(self): import feeds title = "%s RSS Feed" % self.title url = feeds.ChannelFeed.get_url(self) return dict(title=title, url=url) def get_template_names(self, template_name, alternates=None): alternates = alternates or [] alternates = [os.path.join(p, template_name) for p in alternates] templates = [] templates += alternates templates.append(os.path.join('blog', template_name)) return templates
class Page(models.Model): base = models.ForeignKey(PageBase, blank=True, null=True) parent = models.ForeignKey("Page", blank=True, null=True) path = models.CharField("Page path", max_length=255, blank=True) title = models.CharField("Page Title", max_length=100) slug = models.SlugField("Slug", max_length=100, db_index=True) inherit = models.BooleanField("Inherit parent's content?", default=False) created_time = models.DateTimeField(auto_now_add=True) edit_time = models.DateTimeField(auto_now=True) published = models.BooleanField("Display on site?", default=False) promoted = models.BooleanField("Display in children list?", default=True) content = MarkupField(default="", blank=True, renderer=render) objects = models.Manager() published_pages = PublishedPageManager() version = models.CharField("Version", max_length=100, default="live") version_id = models.IntegerField("Parent Page ID", blank=True, null=True) allow_comments = models.BooleanField(default=True) show_comments = models.BooleanField(default=True) def __unicode__(self): if self.version != 'live': return "%s (%s)" % (self.path, self.version) return self.path def serialize(self): return { "title": self.title, "slug": self.slug, "created_time": self.created_time.ctime(), "edit_time": self.edit_time.ctime() if self.edit_time else None, "published": self.published, "content": self.content, "content_html": self.content_html, "version": self.version } def get_sections(self): visited = set() sections_to_combine = [] page = self while page is not None and page.id not in visited: visited.add(page.id) sections_to_combine.append(page.content_data.get('sections')) if not page.inherit: break page = page.parent sections_to_combine = sections_to_combine[::-1] if self.base is not None: sections_to_combine.append(self.base.content_data.get('sections')) sections = combine_sections(*sections_to_combine) return sections def get_template_names(self): templates = ["page/page.html"] if self.base and self.base.template: templates.insert(0, self.base.template) return templates @models.permalink def get_absolute_url(self): return ("page", (self.path, )) def save(self, *args, **kwargs): self.create_path() return super(Page, self).save(*args, **kwargs) def create_path(self): pages_checked = set() page = self page_components = [] while page is not None and page.id not in pages_checked: page_components.append(page.slug) pages_checked.add(page.id) page = page.parent path = "/".join(page_components[::-1]) self.path = path @classmethod def page_from_path(cls, path): components = path.split('/') page = None for component in components: try: page = Page.objects.get(slug=component, parent=page, published=True, version='live') except Page.DoesNotExist: return None return page def get_children(self): children = Page.published_pages.all() return children def get_promoted_children(self): children = self.get_children().filter(promoted=True) return children def get_parent_version(self): if self.version_id is None: return self parent_page = Page.objects.get(self.version_id) return parent_page def get_version(self, version): """ Retrieve a versioned page. """ if self.version == version: return self parent_version_id = self.get_parent_version().id try: versioned_page = Page.objects.get(version_id=parent_version_id, version=version) return versioned_page except Page.DoesNotExist: versioned_page = Page(version_id=parent_version_id, published=False, version=version) versioned_page.save() copy_attribs = [ 'parent', 'path', 'title', 'slug', 'inherit', 'created_time', 'edit_time', 'promoted' ] for attrib in copy_attribs: setattr(versioned_page, attrib, getattr(self, attrib)) versioned_page.save() return versioned_page def delete_version(self, version): """Removes the draft object associated with a page.""" parent_version_id = self.get_parent_version().id try: versioned_page = Page.objects.get(version_id=parent_version_id, version=version) versioned_page.delete() except Page.DoesNotExist: pass def version_exists(self, version): parent_version_id = self.get_parent_version().id try: versioned_page = Page.objects.get(version_id=parent_version_id, version=version) return True except Page.DoesNotExist: return False