first commit

This commit is contained in:
2025-09-19 15:19:32 +05:00
commit d160410cd9
305 changed files with 9509 additions and 0 deletions

View File

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,36 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.blog.models import CategoryModel, PostimagesModel, PostModel, TagModel
@admin.register(PostModel)
class PostAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
)
@admin.register(TagModel)
class TagAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
)
@admin.register(CategoryModel)
class CategoryAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
)
@admin.register(PostimagesModel)
class PostimagesAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
)

6
core/apps/blog/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class ModuleConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "core.apps.blog"

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,43 @@
from django_filters import rest_framework as filters
from core.apps.blog.models import CategoryModel, PostimagesModel, PostModel, TagModel
class PostFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = PostModel
fields = [
"name",
]
class TagFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = TagModel
fields = [
"name",
]
class CategoryFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = CategoryModel
fields = [
"name",
]
class PostimagesFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = PostimagesModel
fields = [
"name",
]

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,31 @@
from django import forms
from core.apps.blog.models import CategoryModel, PostimagesModel, PostModel, TagModel
class PostForm(forms.ModelForm):
class Meta:
model = PostModel
fields = "__all__"
class TagForm(forms.ModelForm):
class Meta:
model = TagModel
fields = "__all__"
class CategoryForm(forms.ModelForm):
class Meta:
model = CategoryModel
fields = "__all__"
class PostimagesForm(forms.ModelForm):
class Meta:
model = PostimagesModel
fields = "__all__"

View File

@@ -0,0 +1,78 @@
# Generated by Django 5.1.3 on 2025-09-19 10:19
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='CategoryModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255, verbose_name='name')),
],
options={
'verbose_name': 'CategoryModel',
'verbose_name_plural': 'CategoryModels',
'db_table': 'category',
},
),
migrations.CreateModel(
name='PostModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('title', models.CharField(max_length=255, verbose_name='name')),
('text', models.TextField(verbose_name='text')),
('slug', models.SlugField(max_length=255, unique=True, verbose_name='slug')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='updated')),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='post_category', to='blog.categorymodel', verbose_name='category')),
],
options={
'verbose_name': 'PostModel',
'verbose_name_plural': 'PostModels',
'db_table': 'post',
},
),
migrations.CreateModel(
name='PostimagesModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('image', models.ImageField(upload_to='post/images/', verbose_name='image')),
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='post_images', to='blog.postmodel', verbose_name='post')),
],
options={
'verbose_name': 'PostimagesModel',
'verbose_name_plural': 'PostimagesModels',
'db_table': 'PostImages',
},
),
migrations.CreateModel(
name='TagModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255, verbose_name='name')),
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='post_tags', to='blog.postmodel', verbose_name='post')),
],
options={
'verbose_name': 'TagModel',
'verbose_name_plural': 'TagModels',
'db_table': 'tag',
},
),
]

View File

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,92 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from django.utils.text import slugify
class CategoryModel(AbstractBaseModel):
name = models.CharField(verbose_name=_("name"), max_length=255)
def __str__(self):
return str(self.pk)
@classmethod
def _create_fake(self):
return self.objects.create(
name="mock",
)
class Meta:
db_table = "category"
verbose_name = _("CategoryModel")
verbose_name_plural = _("CategoryModels")
class PostModel(AbstractBaseModel):
title = models.CharField(verbose_name=_("name"), max_length=255)
text = models.TextField(verbose_name=_("text"))
category = models.ForeignKey(CategoryModel, related_name="post_category", verbose_name=_("category"),
on_delete=models.CASCADE)
slug = models.SlugField(verbose_name=_("slug"), max_length=255, unique=True)
created = models.DateTimeField(verbose_name=_("created"), auto_now_add=True)
updated = models.DateTimeField(verbose_name=_("updated"), auto_now=True)
def __str__(self):
return str(self.pk)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
@classmethod
def _create_fake(self):
return self.objects.create(
name="mock",
text="mock",
)
class Meta:
db_table = "post"
verbose_name = _("PostModel")
verbose_name_plural = _("PostModels")
class TagModel(AbstractBaseModel):
name = models.CharField(verbose_name=_("name"), max_length=255)
post = models.ForeignKey(PostModel, verbose_name=_("post"), related_name="post_tags", on_delete=models.CASCADE)
def __str__(self):
return str(self.pk)
@classmethod
def _create_fake(self):
return self.objects.create(
name="mock",
post=PostModel._create_fake(),
)
class Meta:
db_table = "tag"
verbose_name = _("TagModel")
verbose_name_plural = _("TagModels")
class PostimagesModel(AbstractBaseModel):
image = models.ImageField(verbose_name=_("image"), upload_to="post/images/")
post = models.ForeignKey(PostModel, verbose_name=_("post"), related_name="post_images", on_delete=models.CASCADE)
def __str__(self):
return str(self.pk)
@classmethod
def _create_fake(self):
return self.objects.create(
image="resources/static/images/default_avatar.jpg",
post=PostModel._create_fake(),
)
class Meta:
db_table = "PostImages"
verbose_name = _("PostimagesModel")
verbose_name_plural = _("PostimagesModels")

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,45 @@
from rest_framework import permissions
class PostPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True
class TagPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True
class CategoryPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True
class PostimagesPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,3 @@
from .category import * # noqa
from .post import * # noqa
from .tag import * # noqa

View File

@@ -0,0 +1,28 @@
from rest_framework import serializers
from core.apps.blog.models import CategoryModel
class BaseCategorySerializer(serializers.ModelSerializer):
class Meta:
model = CategoryModel
fields = [
"id",
"name",
]
class ListCategorySerializer(BaseCategorySerializer):
class Meta(BaseCategorySerializer.Meta): ...
class RetrieveCategorySerializer(BaseCategorySerializer):
class Meta(BaseCategorySerializer.Meta): ...
class CreateCategorySerializer(BaseCategorySerializer):
class Meta(BaseCategorySerializer.Meta):
fields = [
"id",
"name",
]

View File

@@ -0,0 +1,29 @@
from core.apps.blog.models import PostModel
from rest_framework import serializers
class BasePostSerializer(serializers.ModelSerializer):
class Meta:
model = PostModel
fields = [
"id",
"name",
]
class ListPostSerializer(BasePostSerializer):
class Meta(BasePostSerializer.Meta): ...
class RetrievePostSerializer(BasePostSerializer):
class Meta(BasePostSerializer.Meta): ...
class CreatePostSerializer(BasePostSerializer):
class Meta(BasePostSerializer.Meta):
fields = [
"id",
"name",
]

View File

@@ -0,0 +1,28 @@
from rest_framework import serializers
from core.apps.blog.models import TagModel
class BaseTagSerializer(serializers.ModelSerializer):
class Meta:
model = TagModel
fields = [
"id",
"name",
]
class ListTagSerializer(BaseTagSerializer):
class Meta(BaseTagSerializer.Meta): ...
class RetrieveTagSerializer(BaseTagSerializer):
class Meta(BaseTagSerializer.Meta): ...
class CreateTagSerializer(BaseTagSerializer):
class Meta(BaseTagSerializer.Meta):
fields = [
"id",
"name",
]

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,20 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from core.apps.blog.models import CategoryModel, PostimagesModel, PostModel, TagModel
@receiver(post_save, sender=PostModel)
def PostSignal(sender, instance, created, **kwargs): ...
@receiver(post_save, sender=TagModel)
def TagSignal(sender, instance, created, **kwargs): ...
@receiver(post_save, sender=CategoryModel)
def CategorySignal(sender, instance, created, **kwargs): ...
@receiver(post_save, sender=PostimagesModel)
def PostimagesSignal(sender, instance, created, **kwargs): ...

View File

@@ -0,0 +1 @@
from .test_post import * # noqa

View File

@@ -0,0 +1,173 @@
from django.test import TestCase
from django.urls import reverse
from rest_framework.test import APIClient
from core.apps.blog.models import CategoryModel, PostimagesModel, PostModel, TagModel
class PostTest(TestCase):
def _create_data(self):
return PostModel._create_fake()
def setUp(self):
self.client = APIClient()
self.instance = self._create_data()
self.urls = {
"list": reverse("post -list"),
"retrieve": reverse("post -detail", kwargs={"pk": self.instance.pk}),
"retrieve-not-found": reverse("post -detail", kwargs={"pk": 1000}),
}
def test_create(self):
self.assertTrue(True)
def test_update(self):
self.assertTrue(True)
def test_partial_update(self):
self.assertTrue(True)
def test_destroy(self):
self.assertTrue(True)
def test_list(self):
response = self.client.get(self.urls["list"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve(self):
response = self.client.get(self.urls["retrieve"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve_not_found(self):
response = self.client.get(self.urls["retrieve-not-found"])
self.assertFalse(response.json()["status"])
self.assertEqual(response.status_code, 404)
class TagTest(TestCase):
def _create_data(self):
return TagModel._create_fake()
def setUp(self):
self.client = APIClient()
self.instance = self._create_data()
self.urls = {
"list": reverse("tag-list"),
"retrieve": reverse("tag-detail", kwargs={"pk": self.instance.pk}),
"retrieve-not-found": reverse("tag-detail", kwargs={"pk": 1000}),
}
def test_create(self):
self.assertTrue(True)
def test_update(self):
self.assertTrue(True)
def test_partial_update(self):
self.assertTrue(True)
def test_destroy(self):
self.assertTrue(True)
def test_list(self):
response = self.client.get(self.urls["list"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve(self):
response = self.client.get(self.urls["retrieve"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve_not_found(self):
response = self.client.get(self.urls["retrieve-not-found"])
self.assertFalse(response.json()["status"])
self.assertEqual(response.status_code, 404)
class CategoryTest(TestCase):
def _create_data(self):
return CategoryModel._create_fake()
def setUp(self):
self.client = APIClient()
self.instance = self._create_data()
self.urls = {
"list": reverse("category-list"),
"retrieve": reverse("category-detail", kwargs={"pk": self.instance.pk}),
"retrieve-not-found": reverse("category-detail", kwargs={"pk": 1000}),
}
def test_create(self):
self.assertTrue(True)
def test_update(self):
self.assertTrue(True)
def test_partial_update(self):
self.assertTrue(True)
def test_destroy(self):
self.assertTrue(True)
def test_list(self):
response = self.client.get(self.urls["list"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve(self):
response = self.client.get(self.urls["retrieve"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve_not_found(self):
response = self.client.get(self.urls["retrieve-not-found"])
self.assertFalse(response.json()["status"])
self.assertEqual(response.status_code, 404)
class PostimagesTest(TestCase):
def _create_data(self):
return PostimagesModel._create_fake()
def setUp(self):
self.client = APIClient()
self.instance = self._create_data()
self.urls = {
"list": reverse("PostImages-list"),
"retrieve": reverse("PostImages-detail", kwargs={"pk": self.instance.pk}),
"retrieve-not-found": reverse("PostImages-detail", kwargs={"pk": 1000}),
}
def test_create(self):
self.assertTrue(True)
def test_update(self):
self.assertTrue(True)
def test_partial_update(self):
self.assertTrue(True)
def test_destroy(self):
self.assertTrue(True)
def test_list(self):
response = self.client.get(self.urls["list"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve(self):
response = self.client.get(self.urls["retrieve"])
self.assertTrue(response.json()["status"])
self.assertEqual(response.status_code, 200)
def test_retrieve_not_found(self):
response = self.client.get(self.urls["retrieve-not-found"])
self.assertFalse(response.json()["status"])
self.assertEqual(response.status_code, 404)

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,23 @@
from modeltranslation.translator import TranslationOptions, register
from core.apps.blog.models import CategoryModel, PostimagesModel, PostModel, TagModel
@register(PostModel)
class PostTranslation(TranslationOptions):
fields = []
@register(TagModel)
class TagTranslation(TranslationOptions):
fields = []
@register(CategoryModel)
class CategoryTranslation(TranslationOptions):
fields = []
@register(PostimagesModel)
class PostimagesTranslation(TranslationOptions):
fields = []

9
core/apps/blog/urls.py Normal file
View File

@@ -0,0 +1,9 @@
from .views import CategoryView, TagView, PostView
from django.urls import include, path
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register("post", PostView, basename="post")
router.register("category", CategoryView, basename="category")
router.register("tag", TagView, basename="tag")
urlpatterns = [path("", include(router.urls))]

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,29 @@
# from django.core.exceptions import ValidationError
class PostValidator:
def __init__(self): ...
def __call__(self):
return True
class TagValidator:
def __init__(self): ...
def __call__(self):
return True
class CategoryValidator:
def __init__(self): ...
def __call__(self):
return True
class PostimagesValidator:
def __init__(self): ...
def __call__(self):
return True

View File

@@ -0,0 +1 @@
from .post import * # noqa

View File

@@ -0,0 +1,59 @@
from django_core.mixins import BaseViewSetMixin
from drf_spectacular.utils import extend_schema
from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet
from core.apps.blog.models import CategoryModel, PostModel, TagModel
from core.apps.blog.serializers.post import (
CreateCategorySerializer,
CreatePostSerializer,
CreateTagSerializer,
ListCategorySerializer,
ListPostSerializer,
ListTagSerializer,
RetrieveCategorySerializer,
RetrievePostSerializer,
RetrieveTagSerializer,
)
@extend_schema(tags=["post"])
class PostView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = PostModel.objects.all()
serializer_class = ListPostSerializer
permission_classes = [AllowAny]
action_permission_classes = {}
action_serializer_class = {
"list": ListPostSerializer,
"retrieve": RetrievePostSerializer,
"create": CreatePostSerializer,
}
@extend_schema(tags=["tag"])
class TagView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = TagModel.objects.all()
serializer_class = ListTagSerializer
permission_classes = [AllowAny]
action_permission_classes = {}
action_serializer_class = {
"list": ListTagSerializer,
"retrieve": RetrieveTagSerializer,
"create": CreateTagSerializer,
}
@extend_schema(tags=["category"])
class CategoryView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = CategoryModel.objects.all()
serializer_class = ListCategorySerializer
permission_classes = [AllowAny]
action_permission_classes = {}
action_serializer_class = {
"list": ListCategorySerializer,
"retrieve": RetrieveCategorySerializer,
"create": CreateCategorySerializer,
}