Skip to content

Commit 215736d

Browse files
Merge pull request #19 from RustamovAkrom/main
Main
2 parents c14f710 + 1564ffb commit 215736d

29 files changed

+4520
-49
lines changed

apps/blog/admin.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from django.contrib import admin
22
from .models import Post, PostComment, PostLike, PostDislike, PostCommentLike
33

4+
from unfold.admin import ModelAdmin
5+
46

57
@admin.register(Post)
6-
class PostAdmin(admin.ModelAdmin):
8+
class PostAdmin(ModelAdmin):
79
list_display = ["title", "content", "author", "is_active"]
810
search_fields = ["title", "content"]
911
list_filter = ["author", "is_active"]
@@ -12,20 +14,20 @@ class PostAdmin(admin.ModelAdmin):
1214

1315

1416
@admin.register(PostComment)
15-
class PostCommentAdmin(admin.ModelAdmin):
17+
class PostCommentAdmin(ModelAdmin):
1618
pass
1719

1820

1921
@admin.register(PostLike)
20-
class PostLikeAdmin(admin.ModelAdmin):
22+
class PostLikeAdmin(ModelAdmin):
2123
pass
2224

2325

2426
@admin.register(PostDislike)
25-
class PostDislike(admin.ModelAdmin):
27+
class PostDislike(ModelAdmin):
2628
pass
2729

2830

2931
@admin.register(PostCommentLike)
30-
class PostCommentLikeAdmin(admin.ModelAdmin):
32+
class PostCommentLikeAdmin(ModelAdmin):
3133
pass

apps/blog/filters.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import django_filters
2+
3+
from .models import Post
4+
5+
6+
class PostFilter(django_filters.FilterSet):
7+
title = django_filters.CharFilter(lookup_expr="icontains")
8+
description = django_filters.CharFilter(lookup_expr="icontains")
9+
content = django_filters.CharFilter(lookup_expr="icontains")
10+
created_at = django_filters.DateFromToRangeFilter()
11+
12+
class Meta:
13+
model = Post
14+
fields = ["title", "description", "content", "created_at"]

apps/blog/utils.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,44 @@
11
from django.db.models import QuerySet
22
from django.db.models import Q
3-
from django.core.paginator import Paginator, Page, EmptyPage, PageNotAnInteger
3+
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
4+
from django.core.paginator import (
5+
Paginator,
6+
Page,
7+
EmptyPage,
8+
PageNotAnInteger,
9+
InvalidPage,
10+
)
11+
from django.conf import settings
412

513
from .models import PostLike, PostDislike, Post, PostComment
614

715

8-
def get_search_model_queryset(
9-
model_queryset: QuerySet, search_query: str = None
10-
) -> QuerySet:
11-
if not search_query:
16+
def get_search_model_queryset(model_queryset: QuerySet, query: str = None) -> QuerySet:
17+
if not query:
1218
return model_queryset
1319

14-
search_query = model_queryset.filter(
15-
Q(title__icontains=search_query)
16-
| Q(description__icontains=search_query)
17-
| Q(content__icontains=search_query)
18-
)
19-
20-
return search_query
20+
search_vector = SearchVector("title", "description", "content")
21+
search_query = SearchQuery(query)
22+
23+
if settings.DATABASES["default"]["ENGINE"] == "django.db.backends.postgresql":
24+
# PostgreSQL search
25+
queryset = (
26+
model_queryset.annotate(
27+
search=search_vector,
28+
rank=SearchRank(search_vector, search_query),
29+
)
30+
.filter(search=search_query)
31+
.order_by("-rank")
32+
)
33+
else:
34+
# SQLite3 search
35+
queryset = model_queryset.filter(
36+
Q(title__icontains=query)
37+
| Q(description__icontains=query)
38+
| Q(content__icontains=query)
39+
)
40+
41+
return queryset
2142

2243

2344
def get_pagination_obj(model_queryset: QuerySet, page: int = 1, size: int = 4) -> Page:
@@ -29,6 +50,9 @@ def get_pagination_obj(model_queryset: QuerySet, page: int = 1, size: int = 4) -
2950
except PageNotAnInteger:
3051
page_obj = paginator.page(1)
3152

53+
except InvalidPage:
54+
page_obj = paginator.page(1)
55+
3256
except EmptyPage:
3357
page_obj = paginator.page(paginator.num_pages)
3458

apps/shared/management/commands/createadmin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django.core.management import BaseCommand
55

66
from dotenv import load_dotenv
7+
78
load_dotenv()
89

910

apps/users/admin.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
from django.contrib import admin
2+
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin # noqa
23
from .models import User, UserProfile
34

5+
from unfold.admin import ModelAdmin
6+
47

58
@admin.register(User)
6-
class UserAdmin(admin.ModelAdmin):
9+
class UserAdmin(ModelAdmin):
710
list_display = ["username", "post_count"]
8-
search_fields = ["first_name", "last_name", "username"]
11+
search_fields = ["first_name", "last_name", "username", "email"]
912
list_display_links = ["username"]
1013

1114
def get_post_count(self):
1215
return self.post_count
1316

1417

1518
@admin.register(UserProfile)
16-
class UserProfileAdmin(admin.ModelAdmin):
17-
pass
19+
class UserProfileAdmin(ModelAdmin):
20+
list_display = ["user", "avatar", "bio"]

apps/users/api_endpoints/users/User/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,6 @@ def _create_user():
102102
_check_user_error_field()
103103
_check_user_passwords_field()
104104
_create_user()
105+
106+
def test_api_user_update(self):
107+
pass
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from rest_framework.test import APITestCase
2+
from rest_framework_simplejwt.tokens import RefreshToken
3+
from apps.users.models import UserProfile, User # noqa
4+
5+
6+
class UserProfileApiTestCase(APITestCase):
7+
def setUp(self) -> None:
8+
self.username = "Admin"
9+
self.email = "[email protected]"
10+
self.password = "password"
11+
user = User.objects.create(
12+
username=self.username,
13+
email=self.email,
14+
)
15+
user.set_password(self.password)
16+
user.save()
17+
self.user = user
18+
refresh = RefreshToken.for_user(self.user)
19+
self.token = str(refresh.access_token)
20+
return super().setUp()

apps/users/middleware.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
class JWTAuthMiddleware(MiddlewareMixin):
1212
def process_request(self, request):
13+
# If admin auth for session
1314
if request.path.startswith("/admin"):
1415
return
1516

core/asgi.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
"""
2-
ASGI config for config project.
3-
4-
It exposes the ASGI callable as a module-level variable named ``application``.
5-
6-
For more information on this file, see
7-
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
8-
"""
9-
101
import os
112

123
from django.core.asgi import get_asgi_application
134

14-
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
5+
from dotenv import load_dotenv
6+
7+
load_dotenv()
8+
9+
os.environ.setdefault(
10+
"DJANGO_SETTINGS_MODULE",
11+
os.getenv("DJANGO_SETTINGS_MODULE", "core.settings.development"),
12+
)
1513

1614
application = get_asgi_application()
15+
16+
app = application

core/config/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
from .apps import * # noqa
22
from .jwt import * # noqa
33
from .rest_framework import * # noqa
4+
from .unfold_navigation import * # noqa
5+
from .unfold import * # noqa
6+
7+
# from .cheditor5 import * # noqa

0 commit comments

Comments
 (0)