From cd0cc3b2c726f08506852f8fe9ad249ac547cd3a Mon Sep 17 00:00:00 2001 From: Sepehr Akbarzadeh Date: Thu, 29 Aug 2024 01:53:45 +0330 Subject: [PATCH] style(sage_blog): refactor code and do black, isort and pre-commit rules --- .gitignore | 2 +- README.md | 2 +- sage_blog/admin/__init__.py | 2 +- sage_blog/admin/category.py | 12 +- sage_blog/admin/post.py | 9 +- .../management/commands/generate_blog_data.py | 3 +- sage_blog/models/__init__.py | 4 +- sage_blog/models/category.py | 2 +- sage_blog/models/faq.py | 1 - sage_blog/models/post.py | 3 +- sage_blog/models/tag.py | 2 +- .../repository/generator/data_generator.py | 230 ++++++++---------- sage_blog/repository/managers/tag.py | 4 +- sage_blog/repository/queryset/category.py | 16 +- sage_blog/repository/queryset/post.py | 24 +- sage_blog/settings/check.py | 11 +- sage_blog/views/mixins/context.py | 2 +- 17 files changed, 150 insertions(+), 179 deletions(-) diff --git a/.gitignore b/.gitignore index e18e8c9..9140c71 100644 --- a/.gitignore +++ b/.gitignore @@ -168,4 +168,4 @@ manage.py # Ignore all migrations files except __init__.py **/migrations/* -!**/migrations/__init__.py \ No newline at end of file +!**/migrations/__init__.py diff --git a/README.md b/README.md index 1f4ca36..596d268 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# django-sage-blog \ No newline at end of file +# django-sage-blog diff --git a/sage_blog/admin/__init__.py b/sage_blog/admin/__init__.py index 4a79e58..dbd8a22 100644 --- a/sage_blog/admin/__init__.py +++ b/sage_blog/admin/__init__.py @@ -1,4 +1,4 @@ from .category import PostCategoryAdmin from .faq import PostFaqAdmin -from .tag import PostTagAdmin from .post import PostAdmin +from .tag import PostTagAdmin diff --git a/sage_blog/admin/category.py b/sage_blog/admin/category.py index daecc16..2a6ad99 100644 --- a/sage_blog/admin/category.py +++ b/sage_blog/admin/category.py @@ -1,8 +1,8 @@ from django.contrib import admin from django.utils.translation import gettext_lazy as _ -from sage_blog.models import PostCategory from sage_blog.admin.filters import PostsStatusFilter +from sage_blog.models import PostCategory @admin.register(PostCategory) @@ -18,11 +18,11 @@ class PostCategoryAdmin(admin.ModelAdmin): # Display settings admin_priority = 1 list_display = ( - "title", - "slug", - "is_published", - "published_posts_count", - "modified_at" + "title", + "slug", + "is_published", + "published_posts_count", + "modified_at", ) list_filter = (PostsStatusFilter, "is_published") search_fields = ("title",) diff --git a/sage_blog/admin/post.py b/sage_blog/admin/post.py index f1d6af7..d01f356 100644 --- a/sage_blog/admin/post.py +++ b/sage_blog/admin/post.py @@ -1,6 +1,5 @@ from django.contrib import admin from django.utils.translation import gettext_lazy as _ - from sorl.thumbnail.admin import AdminImageMixin from sage_blog.models import Post, PostFaq @@ -49,11 +48,9 @@ class PostAdmin(admin.ModelAdmin, AdminImageMixin): ordering = ("-published_at",) readonly_fields = ("created_at", "modified_at", "slug") fieldsets = ( - ("Basic Information", - {"fields": ( - "title", "slug", "category", "is_published" - ) - } + ( + "Basic Information", + {"fields": ("title", "slug", "category", "is_published")}, ), ( "Content Details", diff --git a/sage_blog/management/commands/generate_blog_data.py b/sage_blog/management/commands/generate_blog_data.py index 9f8ccea..2da6575 100644 --- a/sage_blog/management/commands/generate_blog_data.py +++ b/sage_blog/management/commands/generate_blog_data.py @@ -16,7 +16,6 @@ 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() @@ -41,7 +40,7 @@ def handle(self, *args, **kwargs): ) 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( diff --git a/sage_blog/models/__init__.py b/sage_blog/models/__init__.py index 8d168d4..1b37574 100644 --- a/sage_blog/models/__init__.py +++ b/sage_blog/models/__init__.py @@ -1,4 +1,4 @@ -from .post import Post -from .faq import PostFaq from .category import PostCategory +from .faq import PostFaq +from .post import Post from .tag import PostTag diff --git a/sage_blog/models/category.py b/sage_blog/models/category.py index 21563a0..259b445 100644 --- a/sage_blog/models/category.py +++ b/sage_blog/models/category.py @@ -1,7 +1,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ - from sage_tools.mixins.models.base import TimeStampMixin, TitleSlugMixin + from sage_blog.repository.managers import CategoryDataAccessLayer diff --git a/sage_blog/models/faq.py b/sage_blog/models/faq.py index 55005e2..78f9b99 100644 --- a/sage_blog/models/faq.py +++ b/sage_blog/models/faq.py @@ -4,7 +4,6 @@ from django.db import models from django.utils.translation import gettext_lazy as _ - from sage_tools.mixins.models.base import TimeStampMixin diff --git a/sage_blog/models/post.py b/sage_blog/models/post.py index e08718c..bee81c2 100644 --- a/sage_blog/models/post.py +++ b/sage_blog/models/post.py @@ -15,9 +15,10 @@ except ImportError: raise ImportError("Install `readtime` package. Run `pip install readtime` ") -from sage_seo.models.mixins.seo import SEOMixin, BlogDetailJsonLdMixin +from sage_seo.models.mixins.seo import BlogDetailJsonLdMixin, SEOMixin from sage_tools.mixins.models.abstract import PictureOperationAbstract from sage_tools.mixins.models.base import TimeStampMixin, TitleSlugDescriptionMixin + from sage_blog.repository.managers import PostDataAccessLayer diff --git a/sage_blog/models/tag.py b/sage_blog/models/tag.py index def0a17..0c9b6e2 100644 --- a/sage_blog/models/tag.py +++ b/sage_blog/models/tag.py @@ -1,7 +1,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ - from sage_tools.mixins.models.base import TimeStampMixin, TitleSlugMixin + from sage_blog.repository.managers import TagDataAccessLayer diff --git a/sage_blog/repository/generator/data_generator.py b/sage_blog/repository/generator/data_generator.py index 0ff34eb..bba0261 100644 --- a/sage_blog/repository/generator/data_generator.py +++ b/sage_blog/repository/generator/data_generator.py @@ -1,26 +1,18 @@ """Data Generator Layer""" -import logging import functools +import logging -from django.utils.text import slugify from django.contrib.auth import get_user_model from django.core.files.uploadedfile import SimpleUploadedFile - +from django.utils.text import slugify from sage_tools.repository.generator import BaseDataGenerator try: from tqdm import tqdm except ImportError as exc: - raise ImportError( - "Install `tqdm` package. Run `pip install tqdm`." - ) from exc + raise ImportError("Install `tqdm` package. Run `pip install tqdm`.") from exc -from sage_blog.models import ( - PostCategory, - Post, - PostTag, - PostFaq -) +from sage_blog.models import Post, PostCategory, PostFaq, PostTag logger = logging.getLogger(__name__) User = get_user_model() @@ -38,122 +30,112 @@ class DataGeneratorLayer(BaseDataGenerator): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - def create_tags(self, - total, - batch_size=300, - disable_progress_bar=False): + def create_tags(self, total, batch_size=300, disable_progress_bar=False): """Create tag fake data - Parameters - ---------- - total : `int` - total objects to generate data - random_activation : `bool` - when it set to true data may have not be activate to show on website. - batch_size : `int` - this param uses to set how many data prepare bulk create in one query. - disable_progress_bar : `bool` - this param hidden `tqdm` package and skip calculating - progress feature as well. - - Returns - ------- - Tag Queryset - """ + Parameters + ---------- + total : `int` + total objects to generate data + random_activation : `bool` + when it set to true data may have not be activate to show on website. + batch_size : `int` + this param uses to set how many data prepare bulk create in one query. + disable_progress_bar : `bool` + this param hidden `tqdm` package and skip calculating + progress feature as well. + + Returns + ------- + Tag Queryset + """ objs = [ PostTag( - title=word, - slug=slugify(word), - is_published=self.get_random_boolean() - ) + title=word, slug=slugify(word), is_published=self.get_random_boolean() + ) for i in tqdm(range(total), disable=disable_progress_bar, colour="#b8835c") if (word := self.get_random_words(3)) ] - logger.debug('%d Tag Objects created successfully.', total) + logger.debug("%d Tag Objects created successfully.", total) tags = PostTag.objects.bulk_create(objs, batch_size=batch_size) - logger.debug('All Tags saved into database.') + logger.debug("All Tags saved into database.") return tags - def create_post_categories(self, - total, - random_activation=True, - batch_size=300, - disable_progress_bar=False): + def create_post_categories( + self, total, random_activation=True, batch_size=300, disable_progress_bar=False + ): """Create category fake data - Parameters - ---------- - total : `int` - total objects to generate data - random_activation : `bool` - when it set to true data may have not be activate to show on website. - batch_size : `int` - this param uses to set how many data prepare bulk create in one query. - disable_progress_bar : `bool` - this param hidden `tqdm` package and skip - calculating progress feature as well. - - Returns - ------- - PostCategory Queryset - """ + Parameters + ---------- + total : `int` + total objects to generate data + random_activation : `bool` + when it set to true data may have not be activate to show on website. + batch_size : `int` + this param uses to set how many data prepare bulk create in one query. + disable_progress_bar : `bool` + this param hidden `tqdm` package and skip + calculating progress feature as well. + + Returns + ------- + PostCategory Queryset + """ objs = [ PostCategory( - title=word, - slug=slugify(word), - is_published=self.get_random_boolean() - ) + title=word, slug=slugify(word), is_published=self.get_random_boolean() + ) for i in tqdm(range(total), disable=disable_progress_bar, colour="#b8835c") if (word := self.get_random_words(3)) ] - logger.debug('%d post categories Objects created successfully.', total) + logger.debug("%d post categories Objects created successfully.", total) PostCategory.objects.bulk_create(objs, batch_size=batch_size) - logger.debug('post categories saved into database.') + logger.debug("post categories saved into database.") post_category = PostCategory.objects.all() return post_category - def create_posts(self, - total, - tag_per_range=3, - random_activation=True, # noqa: W0613 - batch_size=300, - disable_progress_bar=False): + def create_posts( + self, + total, + tag_per_range=3, + random_activation=True, # noqa: W0613 + batch_size=300, + disable_progress_bar=False, + ): """Create post fake data - Parameters - ---------- - total : `int` - total objects to generate data - random_activation : `bool` - when it set to true data may have not be activate - to show on website. - batch_size : `int` - this param uses to set how many data prepare bulk - create in one query. - disable_progress_bar : `bool` - this param hidden `tqdm` package and skip calculating - progress feature as well. - - Returns - ------- - Posts Queryset - """ + Parameters + ---------- + total : `int` + total objects to generate data + random_activation : `bool` + when it set to true data may have not be activate + to show on website. + batch_size : `int` + this param uses to set how many data prepare bulk + create in one query. + disable_progress_bar : `bool` + this param hidden `tqdm` package and skip calculating + progress feature as well. + + Returns + ------- + Posts Queryset + """ post_categories = PostCategory.objects.all() tags = PostTag.objects.all() img_data, img_name, img_format = self.create_placeholder_image( - 1, - subject="post_gallery" + 1, subject="post_gallery" ) banner_data, banner_name, banner_format = self.create_placeholder_image( - 1, - size=(1980, 660), - subject="post_banner" + 1, size=(1980, 660), subject="post_banner" ) objs = [ Post( @@ -167,72 +149,64 @@ def create_posts(self, picture=SimpleUploadedFile( name=img_name, content=img_data, - content_type=f'image/{img_format.lower()}' + content_type=f"image/{img_format.lower()}", ), banner=SimpleUploadedFile( name=banner_name, content=banner_data, - content_type=f'image/{banner_format.lower()}' + content_type=f"image/{banner_format.lower()}", ), ) for i in tqdm(range(total), disable=disable_progress_bar, colour="#b8835c") - if (word := self.get_random_words(3)) + if (word := self.get_random_words(3)) ] - logger.debug('%d post Objects created successfully.', total) + logger.debug("%d post Objects created successfully.", total) Post.objects.bulk_create(objs, batch_size=batch_size) - logger.debug('posts saved into database.') + logger.debug("posts saved into database.") posts = Post.objects.all() list( tqdm( map( - functools.partial( - self.add_to_m2m, - tags, - 'tags', - tag_per_range - ), - objs - ) + functools.partial(self.add_to_m2m, tags, "tags", tag_per_range), + objs, ) ) + ) return posts - def create_faqs(self, - total, - batch_size=300, - disable_progress_bar=False): + def create_faqs(self, total, batch_size=300, disable_progress_bar=False): """Create FAQ fake data - Parameters - ---------- - total : `int` - total objects to generate data - batch_size : `int` - this param uses to set how many data prepare bulk create in one query. - disable_progress_bar : `bool` - this param hidden `tqdm` package and skip calculating - progress feature as well. - - Returns - ------- - PostFaq Queryset - """ + Parameters + ---------- + total : `int` + total objects to generate data + batch_size : `int` + this param uses to set how many data prepare bulk create in one query. + disable_progress_bar : `bool` + this param hidden `tqdm` package and skip calculating + progress feature as well. + + Returns + ------- + PostFaq Queryset + """ posts = Post.objects.all() objs = [ PostFaq( question=self.get_random_sentence()[:150], answer=self.text.text(5), - post=self.get_random_object(posts) + post=self.get_random_object(posts), ) for i in tqdm(range(total), disable=disable_progress_bar, colour="#b8835c") ] - logger.debug('%d FAQ Objects created successfully.', total) + logger.debug("%d FAQ Objects created successfully.", total) faqs = PostFaq.objects.bulk_create(objs, batch_size=batch_size) - logger.debug('All FAQs saved into database.') + logger.debug("All FAQs saved into database.") return faqs diff --git a/sage_blog/repository/managers/tag.py b/sage_blog/repository/managers/tag.py index 02520e0..ba87fe3 100644 --- a/sage_blog/repository/managers/tag.py +++ b/sage_blog/repository/managers/tag.py @@ -1,4 +1,4 @@ -from typing import Optional, Any +from typing import Any, Optional from django.db.models import Manager, QuerySet @@ -20,7 +20,7 @@ def get_queryset(self): return TagQuerySet(self.model, using=self._db) def filter_recent_tags( - self, days_ago: int = 30, limit: Optional[int] = None, obj: Any=None + self, days_ago: int = 30, limit: Optional[int] = None, obj: Any = None ) -> QuerySet: """ Filter tags that have been used in posts within the specified number of days. diff --git a/sage_blog/repository/queryset/category.py b/sage_blog/repository/queryset/category.py index a590ab7..f4a9ebc 100644 --- a/sage_blog/repository/queryset/category.py +++ b/sage_blog/repository/queryset/category.py @@ -16,9 +16,7 @@ def annotate_total_posts(self): indicates the count of posts in that category. """ published_posts = self.filter_published_posts() - qs = published_posts.annotate( - total_posts=Count("posts") - ) + qs = published_posts.annotate(total_posts=Count("posts")) return qs def filter_published(self, is_published: bool = True): @@ -28,13 +26,11 @@ def filter_published(self, is_published: bool = True): qs = self.filter(is_published=is_published) return qs - def filter_published_posts(self, is_published: bool=True): + def filter_published_posts(self, is_published: bool = True): """ Prefetches related posts for each category in the queryset. """ - published_posts_condition = Q( - posts__is_published=is_published - ) + published_posts_condition = Q(posts__is_published=is_published) published = self.filter_published() qs = published.filter(published_posts_condition) return qs @@ -52,16 +48,14 @@ def exclude_unpublished_posts(self) -> QuerySet: Excludes categories that are only associated with in published or discontinued posts. """ - qs = self.filter( - posts__is_published=True - ) + qs = self.filter(posts__is_published=True) return qs def filter_recent_categories(self, num_categories=5, obj=None): """ Retrieves a specified number of the most recently created categories. If 'obj' is provided, it excludes that object from the results. - + Args: num_categories (int): The number of recent categories to retrieve. obj (Optional[Category]): An optional Category object to exclude diff --git a/sage_blog/repository/queryset/post.py b/sage_blog/repository/queryset/post.py index 87ef7ff..691f99e 100644 --- a/sage_blog/repository/queryset/post.py +++ b/sage_blog/repository/queryset/post.py @@ -5,13 +5,13 @@ from django.db.models import ( BooleanField, Case, - OuterRef, - Subquery, Count, ExpressionWrapper, F, + OuterRef, Q, QuerySet, + Subquery, Value, When, fields, @@ -150,12 +150,14 @@ def full_text_search(self, search_query): elif "mysql" in database_engine or "mariadb" in database_engine: return self.filter( - Q(title__icontains=search_query) | Q(description__icontains=search_query) + Q(title__icontains=search_query) + | Q(description__icontains=search_query) ) elif "sqlite" in database_engine: return self.filter( - Q(title__icontains=search_query) | Q(description__icontains=search_query) + Q(title__icontains=search_query) + | Q(description__icontains=search_query) ) return self @@ -167,8 +169,8 @@ def substring_search(self, search_query): """ if search_query: return self.filter( - Q(title__icontains=search_query) | - Q(description__icontains=search_query) + Q(title__icontains=search_query) + | Q(description__icontains=search_query) ) return self @@ -184,8 +186,8 @@ def trigram_similarity_search(self, search_query): if "postgresql" in database_engine: return ( self.annotate( - similarity=TrigramSimilarity("title", search_query) + - TrigramSimilarity("description", search_query) + similarity=TrigramSimilarity("title", search_query) + + TrigramSimilarity("description", search_query) ) .filter(similarity__gt=0.1) .order_by("-similarity") @@ -195,13 +197,15 @@ def trigram_similarity_search(self, search_query): # MariaDB does not support trigram similarity directly # Mysql does not support trigram similarity directly return self.filter( - Q(title__icontains=search_query) | Q(description__icontains=search_query) + Q(title__icontains=search_query) + | Q(description__icontains=search_query) ) elif "sqlite" in database_engine: # SQLite does not support trigram similarity directly return self.filter( - Q(title__icontains=search_query) | Q(description__icontains=search_query) + Q(title__icontains=search_query) + | Q(description__icontains=search_query) ) return self.none() diff --git a/sage_blog/settings/check.py b/sage_blog/settings/check.py index 1f6431c..32ab56f 100644 --- a/sage_blog/settings/check.py +++ b/sage_blog/settings/check.py @@ -1,6 +1,8 @@ from django.conf import settings -from django.core.checks import Error, Warning as CheckWarning, register -from django.db import connection, OperationalError +from django.core.checks import Error +from django.core.checks import Warning as CheckWarning +from django.core.checks import register +from django.db import OperationalError, connection @register() @@ -19,8 +21,9 @@ def check_postgres_extensions(app_configs, **_kwargs): errors.append( Error( "pg_trgm extension is not installed", - hint=("Run `CREATE EXTENSION pg_trgm;` in " - "your PSQL database." + hint=( + "Run `CREATE EXTENSION pg_trgm;` in " + "your PSQL database." ), id="postgres.E001", ) diff --git a/sage_blog/views/mixins/context.py b/sage_blog/views/mixins/context.py index 3fabfce..47ff671 100644 --- a/sage_blog/views/mixins/context.py +++ b/sage_blog/views/mixins/context.py @@ -1,6 +1,6 @@ from django.views.generic.base import ContextMixin -from sage_blog.models import PostCategory, PostTag, Post +from sage_blog.models import Post, PostCategory, PostTag class SageBlogContextMixin(ContextMixin):