Skip to content

Commit

Permalink
Merge pull request #5 from MohmdFo/main
Browse files Browse the repository at this point in the history
feat(sage_blog): Add is_active field to Category and Tag models and enhance admin and repository feature
  • Loading branch information
sepehr-akbarzadeh authored Aug 18, 2024
2 parents 9880f65 + 4a716c0 commit 5c42e3e
Show file tree
Hide file tree
Showing 21 changed files with 642 additions and 169 deletions.
279 changes: 158 additions & 121 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ python = "^3.12"
django = "^5.0.7"
sorl-thumbnail = "^12.10.0"
readtime = "^3.0.0"
django-sage-tools = "^0.1.3"
django-jsonform = "^2.22.0"
pillow = "^10.4.0"
django-filter = "^24.2"
django-sage-seo = "^0.3.1"
django-sage-seo = "^0.3.4"
tqdm = "^4.66.5"

[tool.poetry.group.dev.dependencies]
black = "^24.4.2"
Expand Down
14 changes: 11 additions & 3 deletions sage_blog/admin/category.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.contrib import admin
from django.db.models import Count, Q, QuerySet
from django.utils.translation import gettext_lazy as _

from sage_blog.models import PostCategory
from sage_blog.admin.filters import PostsStatusFilter


@admin.register(PostCategory)
Expand All @@ -16,16 +18,22 @@ class PostCategoryAdmin(admin.ModelAdmin):

# Display settings
admin_priority = 1
list_display = ("title", "slug", "created_at", "modified_at")
list_filter = ("created_at", "modified_at")
list_display = ("title", "slug", "is_active", "modified_at")
list_filter = (PostsStatusFilter, "is_active")
search_fields = ("title",)
date_hierarchy = "created_at"
ordering = ("title",)
save_on_top = True

# Form layout customization
fieldsets = (
(None, {"fields": ("title", "slug")}),
(None, {"fields": ("title", "slug", "is_active")}),
(_("Timestamps"), {"fields": ("created_at", "modified_at")}),
)
readonly_fields = ("created_at", "modified_at", "slug")

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.join_posts()
# queryset = queryset.prefetch_related("posts")
return queryset
1 change: 1 addition & 0 deletions sage_blog/admin/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .post import PostsStatusFilter
20 changes: 20 additions & 0 deletions sage_blog/admin/filters/post.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.contrib import admin
from django.utils.translation import gettext_lazy as _


class PostsStatusFilter(admin.SimpleListFilter):
title = _("Posts Status")
parameter_name = "posts_status"

def lookups(self, request, model_admin):
return [
("no_posts", _("No Posts")),
("inactive_posts", _("Only Inactive Posts")),
]

def queryset(self, request, queryset):
if self.value() == "no_posts":
return queryset.filter(posts__isnull=True)
elif self.value() == "inactive_posts":
return queryset.filter_active_posts().distinct()
return queryset
14 changes: 7 additions & 7 deletions sage_blog/admin/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class PostAdmin(admin.ModelAdmin, AdminImageMixin):
"published_at",
"modified_at",
)
list_filter = ("is_active", "category", "tags", "published_at", "modified_at")
list_filter = ("is_active", "category", "published_at", "modified_at")
search_fields = (
"title",
"slug",
Expand Down Expand Up @@ -109,16 +109,16 @@ class PostAdmin(admin.ModelAdmin, AdminImageMixin):
),
)

def get_tags(self, obj):
@staticmethod
@admin.display(description=_("Tags"))
def get_tags(obj):
return ", ".join([tag.title for tag in obj.tags.all()])

get_tags.short_description = _("Tags")

def get_summary(self, obj):
@staticmethod
@admin.display(description=_("Summary"))
def get_summary(obj):
return obj.summary if obj.summary else _("No Summary")

get_summary.short_description = _("Summary")

# Filter customization
def get_queryset(self, request):
queryset = super().get_queryset(request)
Expand Down
4 changes: 2 additions & 2 deletions sage_blog/admin/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ class PostTagAdmin(admin.ModelAdmin):
"""

admin_priority = 3
list_display = ("title", "slug", "created_at", "modified_at")
list_display = ("title", "slug", "is_active", "modified_at")
list_filter = ("created_at", "modified_at")
search_fields = ("title",)
date_hierarchy = "created_at"
save_on_top = True
ordering = ("title",)

fieldsets = (
(None, {"fields": ("title", "slug")}),
(None, {"fields": ("title", "slug", "is_active")}),
(_("Timestamps"), {"fields": ("created_at", "modified_at")}),
)
readonly_fields = ("created_at", "modified_at", "slug")
Empty file.
Empty file.
90 changes: 90 additions & 0 deletions sage_blog/management/commands/generate_blog_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import logging
import timeit
from typing import TextIO

from colorama import init
from django.core.management.base import BaseCommand
from django.utils.text import slugify

from sage_blog.repository.generator import DataGeneratorLayer

logger = logging.getLogger(__name__)

init(autoreset=True)


class Command(BaseCommand):
help = "Load a list of example data into the database"

def handle(self, *args, **kwargs):

logger.info("Generate Data for Blog")
DGL = DataGeneratorLayer()

self.show_warning_msg("create categories")
start = timeit.default_timer()
DGL.create_post_categories(11)
stop = timeit.default_timer()
self.show_success_msg("create categories finished in: " + str(stop - start))

self.show_warning_msg("create tags")
start = timeit.default_timer()
DGL.create_tags(
total=25,
)
stop = timeit.default_timer()
self.show_success_msg("create tags finished in: " + str(stop - start))

self.show_warning_msg("create posts")
start = timeit.default_timer()
DGL.create_posts(
total=50,
)
stop = timeit.default_timer()
self.show_success_msg("create posts finished in: " + str(stop - start))

self.show_warning_msg("create FAQ")
start = timeit.default_timer()
DGL.create_faqs(
total=50,
)
stop = timeit.default_timer()
self.show_success_msg("create FAQ finished in: " + str(stop - start))

logger.info("Data Generation Finished")

def show_success_msg(self, msg: str) -> TextIO:
"""
Display a success message on the console.
Args:
- msg (str): The success message.
Returns:
TextIO: The output stream.
"""
self.stdout.write(self.style.SUCCESS(msg))

def show_warning_msg(self, msg: str) -> TextIO:
"""
Display a warning message on the console.
Args:
- msg (str): The warning message.
Returns:
TextIO: The output stream.
"""
self.stdout.write(self.style.WARNING(msg))

def show_error_msg(self, msg: str) -> TextIO:
"""
Display an error message on the console.
Args:
- msg (str): The error message.
Returns:
TextIO: The output stream.
"""
self.stdout.write(self.style.ERROR(msg))
12 changes: 12 additions & 0 deletions sage_blog/models/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@
from sage_tools.mixins.models.base import TimeStampMixin, TitleSlugMixin
from sage_blog.repository.managers import CategoryDataAccessLayer


class PostCategory(TitleSlugMixin, TimeStampMixin):
"""
Post Category
"""

is_active = models.BooleanField(
_("Is Active"),
default=True,
help_text=_(
"Indicate whether this category is currently active and should be displayed "
"publicly. Deactivate to hide the category from public view without deleting "
"it."
),
db_comment="Indicates if the category is active (true) or hidden from public view (false).",
)

objects = CategoryDataAccessLayer()

class Meta:
Expand Down
9 changes: 1 addition & 8 deletions sage_blog/models/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from sage_tools.mixins.models.base import TimeStampMixin, TitleSlugDescriptionMixin
from sage_blog.repository.managers import PostDataAccessLayer


class Post(
TitleSlugDescriptionMixin,
PictureOperationAbstract,
Expand Down Expand Up @@ -97,14 +98,6 @@ class Post(

objects = PostDataAccessLayer()

def get_absolute_url(self):
"""
Returns the absolute URL for the blog post detail page.
This method is used to provide a direct link to the blog post's detail view.
"""
return reverse("pages:blog-post-detail", kwargs={"post_slug": self.slug})

class Meta:
"""
Meta options for the Post model.
Expand Down
21 changes: 12 additions & 9 deletions sage_blog/models/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@
from sage_tools.mixins.models.base import TimeStampMixin, TitleSlugMixin
from sage_blog.repository.managers import TagDataAccessLayer


class PostTag(TitleSlugMixin, TimeStampMixin):
"""
Post Tag Model
"""

is_active = models.BooleanField(
_("Is Active"),
default=True,
help_text=_(
"Indicate whether this tag is currently active and should be displayed "
"publicly. Deactivate to hide the tag from public view without deleting "
"it."
),
db_comment="Indicates if the tag is active (true) or hidden from public view (false).",
)

objects = TagDataAccessLayer()

class Meta:
Expand All @@ -25,15 +37,6 @@ class Meta:
db_table = "sage_post_tag"
db_table_comment = "Table for preserving blog post tags"

def get_absolute_url(self):
"""
Get Absolute URL
"""
base_url = reverse("pages:blog-post-list")
query_params = urlencode({"tag": self.slug})
full_url = f"{base_url}?{query_params}"
return full_url

def __str__(self):
return str(self.title)

Expand Down
1 change: 1 addition & 0 deletions sage_blog/repository/generator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .data_generator import DataGeneratorLayer
Loading

0 comments on commit 5c42e3e

Please sign in to comment.