Skip to content

Commit 2e18c9a

Browse files
committed
configure htmx
1 parent e938e2e commit 2e18c9a

25 files changed

+370
-259
lines changed

apps/blog/sitemaps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class PostSitemap(Sitemap):
77
priority = 0.9
88

99
def items(self):
10-
return Post.objects.all()
10+
return Post.published.all()
1111

1212
def lastmod(self, obj):
1313
return obj.updated_at

apps/blog/utils.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.db.models import QuerySet
2+
from django.db.models import Q
23
from django.core.paginator import Paginator, Page, EmptyPage, PageNotAnInteger
34

45
from .models import PostLike, PostDislike, Post, PostComment
@@ -7,19 +8,24 @@
78
def get_search_model_queryset(
89
model_queryset: QuerySet, search_query: str = None
910
) -> QuerySet:
10-
if search_query is None:
11+
if not search_query:
1112
return model_queryset
1213

13-
search_for_title = model_queryset.filter(title__icontains=search_query)
14-
if not search_for_title:
15-
search_for_content = model_queryset.filter(content__icontains=search_query)
16-
if not search_for_content:
17-
queryset = search_for_content
18-
else:
19-
queryset = search_for_content
20-
else:
21-
queryset = search_for_title
22-
return queryset
14+
search_query = model_queryset.filter(
15+
Q(title__icontains=search_query) | Q(description__icontains=search_query) | Q(content__icontains=search_query)
16+
)
17+
18+
return search_query
19+
# search_for_title = model_queryset.filter(title__icontains=search_query)
20+
# if not search_for_title:
21+
# search_for_content = model_queryset.filter(content__icontains=search_query)
22+
# if not search_for_content:
23+
# queryset = search_for_content
24+
# else:
25+
# queryset = search_for_content
26+
# else:
27+
# queryset = search_for_title
28+
# return queryset
2329

2430

2531
def get_pagination_obj(model_queryset: QuerySet, page: int = 1, size: int = 4) -> Page:

apps/blog/views.py

Lines changed: 88 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import datetime
2+
from functools import wraps
3+
from typing import Any
24

35
from django.shortcuts import render, redirect, get_object_or_404
46
from django.contrib.auth.mixins import LoginRequiredMixin
57
from django.views.generic import TemplateView, DeleteView
68
from django.contrib import messages
9+
from django.http import HttpRequest
710
from django.views import View
811
from django.urls import reverse
912

1013
from apps.users.models import User
14+
from apps.shared.mixins import CustomHtmxMixin, render_htmx_or_default
15+
from .models import Post
1116
from .forms import (
1217
PostCreateUpdateForm,
1318
SettingsUserForm,
1419
SettingsUserProfileForm,
1520
)
16-
from .models import Post
1721
from .utils import (
1822
get_search_model_queryset,
1923
get_pagination_obj,
@@ -23,52 +27,48 @@
2327
)
2428

2529

26-
class CustomHtmxMixin:
27-
def dispatch(self, request, *args, **kwargs):
28-
# import pdb; pdb.set_trace()
29-
self.template_htmx = self.template_name
30-
if not self.request.META.get("HTTP_HX_REQUEST"):
31-
self.template_name = "blog/include_blog.html"
32-
return super().dispatch(request, *args, **kwargs)
33-
34-
def get_context_data(self, **kwargs):
35-
kwargs["template_htmx"] = self.template_htmx
36-
return super().get_context_data(**kwargs)
37-
38-
39-
class HomePageView(TemplateView):
30+
class HomePageView(CustomHtmxMixin, TemplateView):
4031
template_name = "blog/home.html"
4132

42-
def get(self, request):
43-
if request.user is not None and request.user.is_authenticated:
44-
posts = Post.published.exclude(author=request.user)
33+
def get_context_data(self, **kwargs):
34+
if self.request.user is not None and self.request.user.is_authenticated:
35+
posts = Post.published.exclude(author=self.request.user)
4536
else:
4637
posts = Post.published.all()
4738

48-
search_query = request.GET.get("search_query", None)
49-
page = request.GET.get("page", 1)
50-
size = request.GET.get("size", 4)
39+
search_query = self.request.GET.get("search_query", None)
40+
page = self.request.GET.get("page", 1)
41+
size = self.request.GET.get("size", 4)
5142

5243
posts = get_search_model_queryset(posts, search_query)
5344

5445
page_obj = get_pagination_obj(posts, page, size)
5546

56-
return render(
57-
request,
58-
"blog/home.html",
59-
{
60-
"page_obj": page_obj,
61-
"size_value": size,
62-
"search_query_value": search_query,
63-
},
64-
)
47+
kwargs["title"] = "Home"
48+
kwargs["page_obj"] = page_obj
49+
kwargs["size_value"] = size
50+
kwargs["search_query_value"] = search_query
51+
52+
return super().get_context_data(**kwargs)
6553

6654

67-
class AboutPageView(TemplateView):
55+
class AboutPageView(CustomHtmxMixin, TemplateView):
6856
template_name = "blog/about.html"
57+
58+
def get_context_data(self, **kwargs):
59+
kwargs["title"] = "About"
60+
return super().get_context_data(**kwargs)
6961

7062

71-
class PostDetailPageView(View):
63+
class ContactsPageView(CustomHtmxMixin, TemplateView):
64+
template_name = "blog/contacts.html"
65+
66+
def get_context_data(self, **kwargs):
67+
kwargs["title"] = "Contacts"
68+
return super().get_context_data(**kwargs)
69+
70+
71+
class PostDetailPageView(CustomHtmxMixin, View):
7272
template_name = "blog/post_detail.html"
7373

7474
def get(self, request, slug):
@@ -77,18 +77,26 @@ def get(self, request, slug):
7777
post_comments = post.post_comments.all().order_by("-created_at")
7878
post.watching += 1
7979
post.save()
80-
return render(
81-
request,
82-
"blog/post_detail.html",
83-
{"post": post, "post_comments": post_comments},
84-
)
8580

81+
context = {
82+
"title": post.title,
83+
"post": post,
84+
"post_comments": post_comments,
85+
"template_htmx": self.template_htmx
86+
}
87+
88+
return render(request, self.template_name, context)
8689

87-
class PostCreatePageView(LoginRequiredMixin, TemplateView):
90+
91+
class PostCreatePageView(CustomHtmxMixin, LoginRequiredMixin, TemplateView):
8892
template_name = "blog/post_create.html"
8993

90-
def get(self, request):
91-
return render(request, "blog/post_create.html", {"form": PostCreateUpdateForm()})
94+
def get_context_data(self, **kwargs):
95+
kwargs["form"] = PostCreateUpdateForm()
96+
kwargs["title"] = "Post Create"
97+
return super().get_context_data(**kwargs)
98+
# def get(self, request):
99+
# return render(request, self.template_name, {"form": PostCreateUpdateForm()})
92100

93101
def post(self, request):
94102
form = PostCreateUpdateForm(request.POST)
@@ -115,30 +123,20 @@ def post(self, request):
115123
return redirect(reverse("blog:post_create"))
116124

117125

118-
class UserPostsPageView(LoginRequiredMixin, View):
119-
template_name = "blog/user_posts.html"
120-
121-
def get(self, request):
122-
123-
search_query_for_user_posts = request.GET.get(
124-
"search_query_for_user_posts", None
125-
)
126-
posts = Post.objects.filter(author=request.user, is_active=True)
127-
128-
if search_query_for_user_posts is not None:
129-
posts = get_search_model_queryset(posts, search_query_for_user_posts)
130-
131-
return render(request, "blog/user_posts.html", {"posts": posts})
132-
133-
134-
class PostUpdateView(LoginRequiredMixin, View):
126+
class PostUpdateView(CustomHtmxMixin, LoginRequiredMixin, TemplateView):
135127
template_name = "blog/post_update.html"
136128

137129
def get(self, request, slug):
138130
post = get_object_or_404(Post, slug=slug, is_active=True)
139131

140132
form = PostCreateUpdateForm(instance=post)
141-
return render(request, "blog/post_update.html", {"form": form, "post": post})
133+
context = {
134+
"title": "Update " + post.title,
135+
"template_htmx": self.template_htmx,
136+
"form": form,
137+
"post": post
138+
}
139+
return render(request, self.template_name, context)
142140

143141
def post(self, request, slug):
144142
post = get_object_or_404(Post, slug=slug)
@@ -152,7 +150,28 @@ def post(self, request, slug):
152150
return redirect(reverse("blog:post_update", kwargs={"slug": slug}))
153151

154152

155-
class PostDeletePageView(LoginRequiredMixin, DeleteView):
153+
class UserPostsPageView(CustomHtmxMixin, LoginRequiredMixin, TemplateView):
154+
template_name = "blog/user_posts.html"
155+
156+
def get(self, request):
157+
158+
search_query_for_user_posts = request.GET.get(
159+
"search_query_for_user_posts", None
160+
)
161+
posts = Post.objects.filter(author=request.user, is_active=True)
162+
163+
if search_query_for_user_posts is not None:
164+
posts = get_search_model_queryset(posts, search_query_for_user_posts)
165+
166+
context = {
167+
"title": "My posts",
168+
"template_htmx": self.template_htmx,
169+
"posts": posts
170+
}
171+
return render(request, self.template_name, context)
172+
173+
174+
class PostDeletePageView(CustomHtmxMixin, LoginRequiredMixin, DeleteView):
156175
template_name = "blog/post_confirm_delete.html"
157176
model = Post
158177

@@ -163,22 +182,21 @@ def post(self, request, slug):
163182
return redirect("blog:user_posts")
164183

165184

166-
class ContactsPageView(TemplateView):
167-
template_name = "blog/contacts.html"
168-
169-
170-
class SettingsPageView(LoginRequiredMixin, View):
171-
template_name = "blog/settings.py"
185+
class SettingsPageView(CustomHtmxMixin, LoginRequiredMixin, View):
186+
template_name = "blog/settings.html"
172187

173188
def get(self, request):
174189
user = get_object_or_404(User, pk=request.user.pk)
175190
user_form = SettingsUserForm(instance=user)
176191
user_profile_form = SettingsUserProfileForm(instance=user.profiles)
177-
return render(
178-
request,
179-
"blog/settings.html",
180-
{"user_form": user_form, "user_profile_form": user_profile_form},
181-
)
192+
context = {
193+
"title": "Settings",
194+
"template_htmx": self.template_htmx,
195+
"user_form": user_form,
196+
"user_profile_form": user_profile_form
197+
}
198+
199+
return render(request, self.template_name, context)
182200

183201
def post(self, request):
184202
user = get_object_or_404(User, pk=request.user.pk)

apps/shared/mixins.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from functools import wraps
2+
3+
from django.http import HttpRequest
4+
from django.shortcuts import render
5+
6+
7+
class CustomHtmxMixin:
8+
def dispatch(self, request, *args, **kwargs):
9+
# import pdb; pdb.set_trace()
10+
self.template_htmx = self.template_name
11+
if not self.request.META.get("HTTP_HX_REQUEST"):
12+
self.template_name = "htmx_blog.html"
13+
return super().dispatch(request, *args, **kwargs)
14+
15+
def get_context_data(self, **kwargs):
16+
kwargs["template_htmx"] = self.template_htmx
17+
return super().get_context_data(**kwargs)
18+
19+
20+
def render_htmx_or_default(template_name, htmx_template_name=None):
21+
def decorator(view_func):
22+
@wraps
23+
def _wrapped_view(request: HttpRequest, *args, **kwargs):
24+
response = view_func(request, *args, **kwargs)
25+
26+
if request.headers.get("HX-Request"):
27+
if htmx_template_name:
28+
return render(request, htmx_template_name, response.context_data)
29+
return render(request, template_name, response.context_data)
30+
return response
31+
return _wrapped_view
32+
return decorator
33+
34+

apps/users/tests.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
1-
from django.test import TestCase # noqa
1+
from django.test import TestCase
2+
3+
from .models import User, UserProfile
4+
5+
6+
class TestUsers(TestCase):
7+
def setUp(self) -> None:
8+
User.objects.create(
9+
username="User",
10+
email="user@example.com",
11+
password="password"
12+
)
13+
return super().setUp()
14+
15+

0 commit comments

Comments
 (0)