-
Notifications
You must be signed in to change notification settings - Fork 28
Feat/issue 117 backend blog page #143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
maxjamchuk
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Отличная работа: блог как отдельный Django-сервис оформлен понятно (модели/админка/урлы/вьюхи/подключение). Перед мёржжем обязательно исправить замечания с CAUTION и WARNING:
CAUTION: починить BlogListView.as_view() (сейчас синтаксическая ошибка);
CAUTION: не отдавать author.email в публичный payload;
WARNING: определиться с политикой публикации (is_published).
Остальные комментарии — рекомендательные (TIP/NOTE).
| from .views import BlogDetailView, BlogListView | ||
|
|
||
| urlpatterns = [ | ||
| path("", BlogListView .as_view(), name="blog_list"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
BlogListView .as_view() — пробел перед точкой делает выражение синтаксически невалидным в Python (будет SyntaxError). Нужно BlogListView.as_view().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Блокирующий синтаксис → чинить до мёрджа
| 'is_published': post.is_published, | ||
| 'duration_minutes': post.duration_minutes, | ||
| 'category': post.category.name, | ||
| 'author': post.author.email, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
BlogDetailView отдаётся post.author.email. Это утечка персональных данных (публичная страница блога не должна раздавать email). Лучше отдавать first_name/username/display_name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
в списке и деталке нет фильтра по is_published а это значит, что потенциально можно показывать черновики и скрытые посты. Обычно делаем так: qs = qs.filter(is_published=True) и в detail: get_object_or_404(BlogPost, pk=pk, is_published=True).
| page_obj = paginator.get_page(page_number) | ||
|
|
||
| posts = list(page_obj.object_list.values( | ||
| 'id', 'title', 'content_short', 'content_full', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
в списке отдаётся content_full для каждого поста — это может быть жирно по трафику. Для списка обычно достаточно content_short, а content_full — только в детальном представлении.
| Q(title__icontains=q) | Q(content_full__icontains=q) | ||
| ) | ||
|
|
||
| paginator = Paginator(qs, 6) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
стоит добавить стабильную сортировку перед пагинацией (order_by('-created_at')), иначе порядок страниц может «прыгать».
| 'duration_minutes': post.duration_minutes, | ||
| 'category': post.category.name, | ||
| 'author': post.author.email, | ||
| 'tags': list(post.tags.values_list('name', flat=True)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
можно оптимизировать: select_related('category','author').prefetch_related('tags'), чтобы не ловить лишние запросы на связанных данных.
| readonly_fields = ("created_at", "updated_at") | ||
|
|
||
| def get_tags(self, obj): | ||
| return ", ".join([tag.name for tag in obj.tags.all()]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
get_tags сейчас делает obj.tags.all() и собирает имена. На списке админки это может дать проблему N+1. Опционально: переопределить get_queryset() и сделать prefetch_related('tags'), а в get_tags использовать values_list.
| class BlogPostAdmin(admin.ModelAdmin): | ||
| list_display = ("id", "title", "author", "category", "created_at", | ||
| "is_published") | ||
| list_filter = ("author", "category", "title", "tags") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
list_filter = ("author", "category", "title", "tags") — фильтрация по заголовку ("title") часто не очень полезна и может раздувать список значений; обычно title отправляем в search_fields.
Issue #117: Implement blog system for /blog page
Created models: BlogPost, BlogCategory, Tag.
Implemented views: BlogListView and BlogDetailView (with InertiaJS support).
Added filtering by category (via GET parameter).
Implemented search by title and full_content (via q GET parameter).
Added pagination using Django’s Paginator (6 items per page).