django-blog-for-html-over-t.../app/website/actions.py

128 lines
3.7 KiB
Python
Raw Permalink Normal View History

2022-05-15 20:58:36 +02:00
from .models import Post, Comment
from .forms import SearchForm, CommentForm
from asgiref.sync import async_to_sync
from django.template.loader import render_to_string
from django.urls import reverse
POST_PER_PAGE = 5
def send_page(self, data={}):
"""Render HTML and send page to client"""
# Prepare context data for page
page = data["page"]
context = {}
data_reverse = {}
match page:
case "all posts":
context = {
"posts": Post.objects.all()[:POST_PER_PAGE],
"form": SearchForm(),
"next_page": 2,
"is_last_page": (Post.objects.count() // POST_PER_PAGE) == 2,
}
case "single post":
post = Post.objects.get(id=data["id"])
context = {
"post": post,
"form": CommentForm(),
"comments": Comment.objects.filter(post=post),
}
data_reverse = {"slug": post.slug}
# Render HTML nav and send to client
context.update({"active_nav": page})
self.send_html(
{
"selector": "#nav",
"html": render_to_string("components/_nav.html", context),
}
)
# Render HTML page and send to client
template_page = page.replace(" ", "_")
self.send_html(
{
"selector": "#main",
"html": render_to_string(f"pages/{template_page}.html", context),
"url": reverse(page, kwargs=data_reverse),
}
)
def search(self, data={}):
"""Search for posts"""
# Prepare context data for page
context = {
"posts": Post.objects.filter(title__icontains=data["search"])[:POST_PER_PAGE]
}
# Render HTML page and send to client
self.send_html(
{
"selector": "#all-posts",
"html": render_to_string("components/all_posts/list.html", context),
}
)
def add_next_posts(self, data={}):
"""Add next posts from pagination"""
# Prepare context data for page
page = int(data["page"]) if "page" in data else 1
start_of_slice = (page - 1) * POST_PER_PAGE
end_of_slice = start_of_slice + POST_PER_PAGE
context = {
"posts": Post.objects.all()[start_of_slice:end_of_slice],
"next_page": page + 1,
"is_last_page": (Post.objects.count() // POST_PER_PAGE) == page,
}
# Add and render HTML with new posts
self.send_html(
{
"selector": "#all-posts",
"html": render_to_string("components/all_posts/list.html", context),
"append": True,
}
)
# Update paginator
self.send_html(
{
"selector": "#paginator",
"html": render_to_string(
"components/all_posts/_button_paginator.html", context
),
}
)
def add_comment(self, data):
"""Add new comment to database"""
# Add post
data_with_post = data.copy()
post = Post.objects.get(id=data["post_id"])
data_with_post["post"] = post
# Set initial values by CommentForm
form = CommentForm(data_with_post)
# Check if form is valid
if form.is_valid():
# Save comment
form.save()
# Render HTML with new comment to all clients
async_to_sync(self.channel_layer.group_send)(
self.room_name,
{
"type": "send.html", # Run "send_html()" method
"selector": "#comments",
"html": render_to_string(
"components/_single_comment.html", {"comment": data}
),
"append": True,
"broadcast": True,
"url": reverse("single post", kwargs={"slug": post.slug}),
},
)