CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-djangocms-blog

The blog application for django CMS providing multilingual blog functionality with advanced content management features

Pending
Overview
Eval results
Files

models.mddocs/

Models and Data Management

Core data models for blog functionality including posts, categories, and CMS plugins with full multilingual support and SEO integration.

Imports

from typing import Optional, List, Dict, Any
from datetime import datetime
from django.db import models
from django.db.models import QuerySet
from django.contrib.auth.models import AbstractUser
from django.http import HttpRequest
from django.utils.functional import cached_property
from cms.models import CMSPlugin, PlaceholderField
from parler.models import TranslatableModel
from meta.models import ModelMeta
from aldryn_apphooks_config.fields import AppHookConfigField
from aldryn_apphooks_config.managers.parler import AppHookConfigTranslatableManager
from djangocms_blog.models import Post, BlogCategory
from djangocms_blog.cms_appconfig import BlogConfig
from djangocms_blog.managers import GenericDateTaggedManager
from djangocms_blog.settings import get_setting

Capabilities

Blog Post Model

The main Post model provides comprehensive blog post functionality with multilingual content, placeholder fields, meta tag support, and extensive relationship management.

class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
    """
    Main blog post model with multilingual and meta support.
    
    Translated fields (via django-parler):
    - title: CharField(max_length=752)
    - slug: SlugField(max_length=752, blank=True, default='')
    - abstract: HTMLField(blank=True, default='')
    - meta_description: TextField(blank=True, default='')
    - meta_keywords: TextField(blank=True, default='')
    - meta_title: CharField(max_length=2000, blank=True, default='')
    - post_text: HTMLField(blank=True, default='')
    - subtitle: CharField(max_length=767, blank=True, default='')
    
    Non-translated fields:
    - author: ForeignKey(User, on_delete=PROTECT, null=True, blank=True)
    - date_created: DateTimeField(auto_now_add=True) 
    - date_modified: DateTimeField(auto_now=True)
    - date_published: DateTimeField(null=True, blank=True)
    - date_published_end: DateTimeField(null=True, blank=True)
    - date_featured: DateTimeField(null=True, blank=True)
    - publish: BooleanField(default=False)
    - featured: BooleanField(default=False)
    - include_in_rss: BooleanField(default=True)
    - enable_comments: BooleanField(default=get_setting('ENABLE_COMMENTS'))
    - enable_liveblog: BooleanField(default=False)
    - sites: ManyToManyField(Site, blank=True)
    - app_config: AppHookConfigField(BlogConfig, null=True)
    - categories: ManyToManyField(BlogCategory, blank=True)
    - tags: TaggableManager(blank=True) 
    - related: SortedManyToManyField('self', blank=True, symmetrical=False)
    - main_image: FilerImageField(null=True, blank=True, on_delete=SET_NULL)
    - main_image_thumbnail: ForeignKey(ThumbnailOption, null=True, blank=True, on_delete=SET_NULL)
    - main_image_full: ForeignKey(ThumbnailOption, null=True, blank=True, on_delete=SET_NULL)
    - content: PlaceholderField('post_content', related_name='post_content')
    - media: PlaceholderField('media', related_name='media')
    - liveblog: PlaceholderField('live_blog', related_name='live_blog')
    """
    
    # Key methods
    def get_absolute_url(self, lang: Optional[str] = None) -> str:
        """Return the absolute URL for the post."""
        
    def get_full_url(self) -> str:
        """Return the full URL including domain."""
        
    def get_image_full_url(self) -> str:
        """Return full URL of the main image."""
        
    def get_image_width(self) -> Optional[int]:
        """Return main image width in pixels."""
        
    def get_image_height(self) -> Optional[int]:
        """Return main image height in pixels."""
        
    def get_title(self) -> str:
        """Return post title with meta fallback."""
        
    def get_description(self) -> str:
        """Return meta description with abstract fallback."""
        
    def get_keywords(self) -> List[str]:
        """Return meta keywords as list."""
        
    def get_tags(self) -> str:
        """Return tags as comma-separated string."""
        
    def get_author(self) -> Optional[AbstractUser]:
        """Return author user object."""
        
    def thumbnail_options(self) -> Dict[str, Any]:
        """Return thumbnail configuration options."""
        
    def full_image_options(self) -> Dict[str, Any]:
        """Return full image configuration options."""
        
    def get_admin_url(self) -> str:
        """Return admin edit URL for the post."""
        
    def should_knock(self, signal_type: str, created: bool = False) -> bool:
        """Return whether to send notification for this post."""
        
    def get_cache_key(self, language: str, prefix: str) -> str:
        """Generate cache key for post in given language."""
        
    @property
    def is_published(self) -> bool:
        """Check if post is published."""
        
    @property
    def guid(self) -> str:
        """Return unique post identifier hash."""
        
    @property
    def date(self) -> datetime:
        """Return featured date or published date."""
        
    @property
    def liveblog_group(self) -> str:
        """Return liveblog group identifier."""
        
    # Manager (accessed via Post.objects)
    objects: GenericDateTaggedManager
    
    # Manager methods:
    # Post.objects.published(current_site=True) - Return QuerySet of published posts
    # Post.objects.published_on_rss(current_site=True) - Return RSS-enabled posts
    # Post.objects.published_future(current_site=True) - Return published including future
    # Post.objects.archived(current_site=True) - Return QuerySet of archived posts  
    # Post.objects.available(current_site=True) - Return QuerySet of available posts for current site
    # Post.objects.filter_by_language(language, current_site=True) - Language filtering
    # Post.objects.on_site(site=None) - Site filtering
    # Post.objects.get_months(queryset=None, current_site=True) - Archive months with counts
    # Post.objects.tagged(other_model=None, queryset=None) - Get tagged items
    # Post.objects.tag_list(other_model=None, queryset=None) - Get common tags
    # Post.objects.tag_cloud(other_model=None, queryset=None, published=True, on_site=False) - Generate tag cloud

Blog Category Model

Multilingual category model for organizing blog posts with SEO support and hierarchical relationships.

class BlogCategory(BlogMetaMixin, TranslatableModel):
    """
    Blog category model with multilingual support.
    
    Translated fields:
    - name: CharField(max_length=752)
    - slug: SlugField(max_length=752, blank=True, db_index=True)
    - meta_description: TextField(blank=True, default='')
    
    Non-translated fields:
    - parent: ForeignKey('self', null=True, blank=True, on_delete=CASCADE, related_name='children')
    - date_created: DateTimeField(auto_now_add=True)
    - date_modified: DateTimeField(auto_now=True)
    - app_config: AppHookConfigField(BlogConfig, null=True)
    """
    
    def get_absolute_url(self, lang: Optional[str] = None) -> str:
        """Return the absolute URL for the category."""
        
    def get_full_url(self) -> str:
        """Return the full URL including domain."""
        
    def descendants(self) -> List['BlogCategory']:
        """Return all descendant categories recursively."""
        
    def get_title(self) -> str:
        """Return category title."""
        
    def get_description(self) -> str:
        """Return category meta description."""
        
    @cached_property
    def linked_posts(self) -> QuerySet:
        """Return posts in this category for current namespace."""
        
    @cached_property
    def count(self) -> int:
        """Return count of posts in this category."""
        
    @cached_property
    def count_all_sites(self) -> int:
        """Return count of posts across all sites."""
        
    # Manager (accessed via BlogCategory.objects)
    objects: AppHookConfigTranslatableManager

CMS Plugin Models

Models for CMS plugins that embed blog content in CMS pages.

class BasePostPlugin(CMSPlugin):
    """Base model for blog-related CMS plugins."""
    app_config: AppHookConfigField(BlogConfig, null=True, blank=True)
    current_site: BooleanField(default=True)
    
    def optimize(self, qs: QuerySet) -> QuerySet:
        """Apply select_related/prefetch_related optimizations to queryset."""
        
    def post_queryset(self, request: Optional[HttpRequest] = None, published_only: bool = True, selected_posts: Optional[List[int]] = None) -> QuerySet:
        """Get filtered post queryset based on plugin configuration."""
    
class LatestPostsPlugin(BasePostPlugin):
    """Plugin model for latest posts display."""
    latest_posts: IntegerField(default=get_setting('LATEST_POSTS'))
    tags: SortedManyToManyField(Tag, blank=True)
    categories: SortedManyToManyField(BlogCategory, blank=True)
    
    def get_posts(self, request: HttpRequest, published_only: bool = True) -> QuerySet:
        """Get posts for latest entries plugin."""
    
class AuthorEntriesPlugin(BasePostPlugin):
    """Plugin model for author posts display."""
    authors: SortedManyToManyField(User, verbose_name=_('Authors'), blank=True)
    latest_posts: IntegerField(default=get_setting('LATEST_POSTS'))
    
    def get_posts(self, request: HttpRequest, published_only: bool = True) -> QuerySet:
        """Get posts for author entries plugin."""
        
    def get_authors(self, request: HttpRequest) -> QuerySet:
        """Get authors with post counts."""
    
class FeaturedPostsPlugin(BasePostPlugin):
    """Plugin model for featured posts display."""
    featured_posts: IntegerField(default=get_setting('LATEST_POSTS'))
    
    def get_posts(self, request: HttpRequest, published_only: bool = True) -> QuerySet:
        """Get posts for featured posts plugin."""
    
class GenericBlogPlugin(BasePostPlugin):
    """Generic blog plugin model base."""
    cache: BooleanField(default=True)

Meta Mixin

Base mixin providing SEO meta tag functionality via django-meta integration.

class BlogMetaMixin(ModelMeta):
    """
    Meta mixin for SEO meta tags using django-meta.
    
    Provides meta tag functionality for models including:
    - OpenGraph tags
    - Twitter Card tags  
    - Google+ tags
    - Schema.org structured data
    """
    
    def get_meta_title(self) -> str:
        """Return meta title for SEO."""
        
    def get_meta_description(self) -> str:
        """Return meta description for SEO."""
        
    def get_meta_keywords(self) -> str:
        """Return meta keywords for SEO."""
        
    def get_meta_url(self) -> str:
        """Return canonical URL for meta tags."""
        
    def get_meta_image(self) -> str:
        """Return meta image URL for social sharing."""

Model Usage Examples

# Creating and managing blog posts
from djangocms_blog.models import Post, BlogCategory
from django.contrib.auth import get_user_model
from django.utils import timezone

User = get_user_model()

# Create a category
category = BlogCategory.objects.create()
category.set_current_language('en')
category.name = 'Technology'
category.slug = 'technology'
category.meta_description = 'Technology related posts'
category.save()

# Create a blog post
post = Post.objects.create(
    author=User.objects.first(),
    app_config=BlogConfig.objects.first(),
    date_published=timezone.now(),
    enable_comments=True,
    featured=True
)

# Set translated content
post.set_current_language('en')
post.title = 'Introduction to Django CMS'
post.slug = 'introduction-django-cms'  
post.abstract = '<p>Learn the basics of Django CMS</p>'
post.post_text = '<p>Django CMS is a powerful content management system...</p>'
post.meta_description = 'Learn Django CMS basics in this comprehensive guide'
post.meta_title = 'Django CMS Tutorial - Complete Guide'
post.save()

# Add to category and tags
post.categories.add(category)
post.tags.add('django', 'cms', 'tutorial')

# Query posts
published_posts = Post.objects.published()
featured_posts = Post.objects.published().filter(featured=True)
category_posts = Post.objects.published().filter(categories=category)
author_posts = Post.objects.published().filter(author=some_user)

# Access post URLs and metadata
url = post.get_absolute_url()
full_url = post.get_full_url()
meta_title = post.get_meta_title()
is_published = post.is_published

Install with Tessl CLI

npx tessl i tessl/pypi-djangocms-blog

docs

admin-forms.md

cms-integration.md

configuration.md

feeds-sitemaps.md

index.md

models.md

templates-utilities.md

views.md

tile.json