From 285f7f3123e8b20bbee47e68db51eed1ef819ae7 Mon Sep 17 00:00:00 2001 From: saahndongransom Date: Thu, 6 Jun 2024 06:16:36 +0100 Subject: [PATCH 01/13] Add blog app and document API endpoints --- .env.example | 2 +- README.md | 1 + ...basemodel_id_alter_eventtag_id_and_more.py | 28 +++++++++ blog/__init__.py | 0 blog/admin.py | 8 +++ blog/apps.py | 15 +++++ blog/migrations/0001_initial.py | 59 +++++++++++++++++++ blog/migrations/__init__.py | 0 blog/models.py | 41 +++++++++++++ blog/permissions.py | 7 +++ blog/serializers.py | 37 ++++++++++++ blog/signals.py | 10 ++++ blog/tasks.py | 7 +++ blog/tests.py | 12 ++++ blog/urls.py | 8 +++ blog/views.py | 59 +++++++++++++++++++ website_api/routes/main.py | 10 ++++ website_api/settings/apps.py | 1 + website_api/settings/base.py | 9 +++ website_api/settings/blog.py | 0 website_api/settings/celery.py | 11 ++++ 21 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py create mode 100644 blog/__init__.py create mode 100644 blog/admin.py create mode 100644 blog/apps.py create mode 100644 blog/migrations/0001_initial.py create mode 100644 blog/migrations/__init__.py create mode 100644 blog/models.py create mode 100644 blog/permissions.py create mode 100644 blog/serializers.py create mode 100644 blog/signals.py create mode 100644 blog/tasks.py create mode 100644 blog/tests.py create mode 100644 blog/urls.py create mode 100644 blog/views.py create mode 100644 website_api/settings/blog.py create mode 100644 website_api/settings/celery.py diff --git a/.env.example b/.env.example index d83fe91..d7bb8bd 100644 --- a/.env.example +++ b/.env.example @@ -9,7 +9,7 @@ DB_HOST='localhost' DB_NAME='django_cameroon' DB_USER='' DB_PASSWORD='' -DB_PORT='3306' +DB_PORT='5432' # Email EMAIL_HOST='smtp.gmail.com' diff --git a/README.md b/README.md index e59dbc7..4687b3b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Assuming postgresql is installed in your computer, follow what's next: sudo -u postgres psql ``` - ```bash + -- Create a database CREATE DATABASE django_website_db; diff --git a/apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py b/apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py new file mode 100644 index 0000000..770e13c --- /dev/null +++ b/apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.1 on 2024-06-05 23:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0002_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='basemodel', + name='id', + field=models.UUIDField(default='4a458960-23ae-4d4d-82cf-b3c783fbb0a5', editable=False, help_text='Unique identifier for this object.', primary_key=True, serialize=False, verbose_name='id'), + ), + migrations.AlterField( + model_name='eventtag', + name='id', + field=models.UUIDField(default='92676ed1-ff1b-401b-aa3e-a380daa5f5f4', editable=False, help_text='Unique identifier for this object.', primary_key=True, serialize=False, verbose_name='id'), + ), + migrations.AlterField( + model_name='speaker', + name='id', + field=models.UUIDField(default='eecf61d8-aa9a-4bd9-8f10-34ba5be2158d', editable=False, help_text='Unique identifier for this object.', primary_key=True, serialize=False, verbose_name='id'), + ), + ] diff --git a/blog/__init__.py b/blog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/admin.py b/blog/admin.py new file mode 100644 index 0000000..ec5d613 --- /dev/null +++ b/blog/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from .models import Tag, Category, Author, Blog, Image + +admin.site.register(Tag) +admin.site.register(Category) +admin.site.register(Author) +admin.site.register(Blog) +admin.site.register(Image) diff --git a/blog/apps.py b/blog/apps.py new file mode 100644 index 0000000..c23d826 --- /dev/null +++ b/blog/apps.py @@ -0,0 +1,15 @@ +from django.apps import AppConfig + + +class BlogConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'blog' + + + +class BlogConfig(AppConfig): + name = 'blog' + + def ready(self): + import blog.signals + diff --git a/blog/migrations/0001_initial.py b/blog/migrations/0001_initial.py new file mode 100644 index 0000000..edd932a --- /dev/null +++ b/blog/migrations/0001_initial.py @@ -0,0 +1,59 @@ +# Generated by Django 5.0.1 on 2024-06-05 23:50 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Author', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('bio', models.TextField()), + ], + ), + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='Blog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('content', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.author')), + ('categories', models.ManyToManyField(to='blog.category')), + ('tags', models.ManyToManyField(to='blog.tag')), + ], + ), + migrations.CreateModel( + name='Image', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image_file', models.ImageField(upload_to='images/')), + ('uploaded_at', models.DateTimeField(auto_now_add=True)), + ('blog_post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='blog.blog')), + ], + ), + ] diff --git a/blog/migrations/__init__.py b/blog/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/models.py b/blog/models.py new file mode 100644 index 0000000..a1d58c2 --- /dev/null +++ b/blog/models.py @@ -0,0 +1,41 @@ +from django.db import models + +class Tag(models.Model): + name = models.CharField(max_length=100) + + def __str__(self): + return self.name + +class Category(models.Model): + name = models.CharField(max_length=100) + + def __str__(self): + return self.name + +class Author(models.Model): + name = models.CharField(max_length=100) + bio = models.TextField() + + def __str__(self): + return self.name + +class Blog(models.Model): + title = models.CharField(max_length=200) + content = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + author = models.ForeignKey(Author, on_delete=models.CASCADE) + categories = models.ManyToManyField(Category) + tags = models.ManyToManyField(Tag) + + def __str__(self): + return self.title + +class Image(models.Model): + image_file = models.ImageField(upload_to='images/') + uploaded_at = models.DateTimeField(auto_now_add=True) + blog_post = models.ForeignKey(Blog, related_name='images', on_delete=models.CASCADE) + + def __str__(self): + return f"Image for {self.blog_post.title}" + diff --git a/blog/permissions.py b/blog/permissions.py new file mode 100644 index 0000000..a188553 --- /dev/null +++ b/blog/permissions.py @@ -0,0 +1,7 @@ +from rest_framework.permissions import BasePermission, SAFE_METHODS + +class IsAuthorOrReadOnly(BasePermission): + def has_object_permission(self, request, view, obj): + if request.method in SAFE_METHODS: + return True + return obj.author == request.user diff --git a/blog/serializers.py b/blog/serializers.py new file mode 100644 index 0000000..2737a30 --- /dev/null +++ b/blog/serializers.py @@ -0,0 +1,37 @@ +from rest_framework import serializers +from .models import Tag, Category, Author, Blog, Image + +class TagSerializer(serializers.ModelSerializer): + class Meta: + model = Tag + fields = '__all__' + +class CategorySerializer(serializers.ModelSerializer): + class Meta: + model = Category + fields = '__all__' + +class AuthorSerializer(serializers.ModelSerializer): + class Meta: + model = Author + fields = '__all__' + +class ImageSerializer(serializers.ModelSerializer): + class Meta: + model = Image + fields = '__all__' + +class BlogSerializer(serializers.ModelSerializer): + author = AuthorSerializer() + categories = CategorySerializer(many=True) + tags = TagSerializer(many=True) + images = ImageSerializer(many=True, read_only=True) + + class Meta: + model = Blog + fields = '__all__' + +class BlogCreateUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = Blog + fields = '__all__' diff --git a/blog/signals.py b/blog/signals.py new file mode 100644 index 0000000..8fd879b --- /dev/null +++ b/blog/signals.py @@ -0,0 +1,10 @@ +from django.db.models.signals import pre_delete +from django.dispatch import receiver +from .models import Image +import os + +@receiver(pre_delete, sender=Image) +def delete_image_file(sender, instance, **kwargs): + if instance.image_file: + if os.path.isfile(instance.image_file.path): + os.remove(instance.image_file.path) diff --git a/blog/tasks.py b/blog/tasks.py new file mode 100644 index 0000000..718d0e6 --- /dev/null +++ b/blog/tasks.py @@ -0,0 +1,7 @@ +from celery import shared_task +from .models import Image + +@shared_task +def handle_image_upload(image_id): + image = Image.objects.get(id=image_id) + diff --git a/blog/tests.py b/blog/tests.py new file mode 100644 index 0000000..c881821 --- /dev/null +++ b/blog/tests.py @@ -0,0 +1,12 @@ + +from django.test import TestCase +from .models import Tag, Category, Author, Blog, Image + +class TagModelTest(TestCase): + def setUp(self): + Tag.objects.create(name="Test Tag") + + def test_tag_creation(self): + tag = Tag.objects.get(name="Test Tag") + self.assertEqual(tag.name, "Test Tag") + diff --git a/blog/urls.py b/blog/urls.py new file mode 100644 index 0000000..8d54abb --- /dev/null +++ b/blog/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('posts/', views.PostList.as_view(), name='post-list'), + path('posts//', views.PostDetail.as_view(), name='post-detail'), + path('posts/create/', views.BlogListCreateView.as_view(), name='post-create'), +] diff --git a/blog/views.py b/blog/views.py new file mode 100644 index 0000000..de75885 --- /dev/null +++ b/blog/views.py @@ -0,0 +1,59 @@ +from rest_framework import generics, permissions +from .models import Blog, Tag, Category, Author, Image +from .serializers import BlogSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer +from .permissions import IsAuthorOrReadOnly +from .tasks import handle_image_upload +from django.http import HttpResponse + +class PostList(generics.ListCreateAPIView): + queryset = Blog.objects.all() + serializer_class = BlogSerializer + + def get_permissions(self): + if self.request.method == 'POST': + self.permission_classes = [permissions.IsAuthenticated] + return super().get_permissions() + +class PostDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = Blog.objects.all() + serializer_class = BlogSerializer + +class TagListView(generics.ListCreateAPIView): + queryset = Tag.objects.all() + serializer_class = TagSerializer + +class CategoryListView(generics.ListCreateAPIView): + queryset = Category.objects.all() + serializer_class = CategorySerializer + +class AuthorListView(generics.ListCreateAPIView): + queryset = Author.objects.all() + serializer_class = AuthorSerializer + +class ImageListView(generics.ListCreateAPIView): + queryset = Image.objects.all() + serializer_class = ImageSerializer + +class ImageCreateView(generics.CreateAPIView): + queryset = Image.objects.all() + serializer_class = ImageSerializer + + def perform_create(self, serializer): + instance = serializer.save() + handle_image_upload.delay(instance.id) + +class BlogListCreateView(generics.ListCreateAPIView): + queryset = Blog.objects.all() + serializer_class = BlogSerializer + + def get_permissions(self): + if self.request.method == 'POST': + self.permission_classes = [permissions.IsAuthenticated] + return super().get_permissions() + +class BlogDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = Blog.objects.all() + serializer_class = BlogSerializer + +def index(request): + return HttpResponse("Hello, world! This is the django cameroon page.") diff --git a/website_api/routes/main.py b/website_api/routes/main.py index 041cf5d..ade2a19 100644 --- a/website_api/routes/main.py +++ b/website_api/routes/main.py @@ -22,6 +22,11 @@ ) BASE_API_URL = "api/v1" +blog_urls = [ + path('blog/', include('blog.urls')), + + +] urlpatterns = ( [ @@ -43,6 +48,11 @@ path(f"{BASE_API_URL}/", include("apps.users.routes.api")), # Events app path(f"{BASE_API_URL}/", include("apps.events.routes.api")), + # Blog app + *blog_urls, + + + ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/website_api/settings/apps.py b/website_api/settings/apps.py index b13c05c..cd8878d 100644 --- a/website_api/settings/apps.py +++ b/website_api/settings/apps.py @@ -8,4 +8,5 @@ CUSTOM_APPS = [ "apps.users", "apps.events", + "blog", ] diff --git a/website_api/settings/base.py b/website_api/settings/base.py index 8a0d13b..852349c 100644 --- a/website_api/settings/base.py +++ b/website_api/settings/base.py @@ -5,6 +5,7 @@ from .apps import CUSTOM_APPS, THIRD_PARTY_APPS + # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) @@ -36,6 +37,9 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + + + ] INSTALLED_APPS += THIRD_PARTY_APPS @@ -142,3 +146,8 @@ # Custom user model AUTH_USER_MODEL = "users.User" + + +CELERY_BROKER_URL = 'redis://localhost:6379/0' +CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' + diff --git a/website_api/settings/blog.py b/website_api/settings/blog.py new file mode 100644 index 0000000..e69de29 diff --git a/website_api/settings/celery.py b/website_api/settings/celery.py new file mode 100644 index 0000000..b39095f --- /dev/null +++ b/website_api/settings/celery.py @@ -0,0 +1,11 @@ +from __future__ import absolute_import, unicode_literals +import os +from celery import Celery + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'website_api.settings') + +app = Celery('website_api') + +app.config_from_object('django.conf:settings', namespace='CELERY') + +app.autodiscover_tasks() From cc0d7edc16f8d99992ea1bcfb29f6c37c9a6ce4a Mon Sep 17 00:00:00 2001 From: saahndongransom Date: Thu, 4 Jul 2024 04:43:37 +0100 Subject: [PATCH 02/13] blog app added --- blog/permissions.py | 3 ++- blog/serializers.py | 36 ++++++++++++++++++++++++--- blog/views.py | 48 +++++++++++++++++++++++++++++++++--- documentation/main.md | 2 +- website_api/settings/apps.py | 4 +++ website_api/settings/base.py | 1 + 6 files changed, 86 insertions(+), 8 deletions(-) diff --git a/blog/permissions.py b/blog/permissions.py index a188553..124c52d 100644 --- a/blog/permissions.py +++ b/blog/permissions.py @@ -1,7 +1,8 @@ + from rest_framework.permissions import BasePermission, SAFE_METHODS class IsAuthorOrReadOnly(BasePermission): def has_object_permission(self, request, view, obj): if request.method in SAFE_METHODS: return True - return obj.author == request.user + return obj.author == request.user \ No newline at end of file diff --git a/blog/serializers.py b/blog/serializers.py index 2737a30..1e25b14 100644 --- a/blog/serializers.py +++ b/blog/serializers.py @@ -14,7 +14,7 @@ class Meta: class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author - fields = '__all__' + fields = ('id', 'name', 'bio') class ImageSerializer(serializers.ModelSerializer): class Meta: @@ -25,13 +25,43 @@ class BlogSerializer(serializers.ModelSerializer): author = AuthorSerializer() categories = CategorySerializer(many=True) tags = TagSerializer(many=True) - images = ImageSerializer(many=True, read_only=True) + images = ImageSerializer(many=True, read_only=True) class Meta: model = Blog - fields = '__all__' + fields = ['author', 'categories', 'tags', 'title', 'content', 'images'] + + def create(self, validated_data): + author_data = validated_data.pop('author') + categories_data = validated_data.pop('categories', []) + tags_data = validated_data.pop('tags', []) + + + author_instance, _ = Author.objects.get_or_create(**author_data) + + + blog = Blog.objects.create(author=author_instance, **validated_data) + + + if categories_data: + categories_instances = [ + Category.objects.get_or_create(**category_data)[0] + for category_data in categories_data + ] + blog.categories.add(*categories_instances) + + + if tags_data: + tags_instances = [ + Tag.objects.get_or_create(**tag_data)[0] + for tag_data in tags_data + ] + blog.tags.add(*tags_instances) + + return blog class BlogCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = Blog fields = '__all__' + diff --git a/blog/views.py b/blog/views.py index de75885..1f5b9fd 100644 --- a/blog/views.py +++ b/blog/views.py @@ -1,9 +1,14 @@ from rest_framework import generics, permissions from .models import Blog, Tag, Category, Author, Image -from .serializers import BlogSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer -from .permissions import IsAuthorOrReadOnly +from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer + +from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer + + from .tasks import handle_image_upload from django.http import HttpResponse +from drf_yasg.utils import swagger_auto_schema +from drf_yasg import openapi class PostList(generics.ListCreateAPIView): queryset = Blog.objects.all() @@ -14,10 +19,47 @@ def get_permissions(self): self.permission_classes = [permissions.IsAuthenticated] return super().get_permissions() + @swagger_auto_schema( + operation_description="Retrieve a list of blog posts", + responses={200: BlogSerializer(many=True)} + ) + def get(self, request, *args, **kwargs): + return super().get(request, *args, **kwargs) + + @swagger_auto_schema( + operation_description="Create a new blog post", + request_body=BlogCreateUpdateSerializer, + responses={201: BlogSerializer} + ) + def post(self, request, *args, **kwargs): + return super().post(request, *args, **kwargs) + class PostDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Blog.objects.all() serializer_class = BlogSerializer + @swagger_auto_schema( + operation_description="Retrieve a blog post", + responses={200: BlogSerializer} + ) + def get(self, request, *args, **kwargs): + return super().get(request, *args, **kwargs) + + @swagger_auto_schema( + operation_description="Update a blog post", + request_body=BlogCreateUpdateSerializer, + responses={200: BlogSerializer} + ) + def put(self, request, *args, **kwargs): + return super().put(request, *args, **kwargs) + + @swagger_auto_schema( + operation_description="Delete a blog post", + responses={204: openapi.Response(description="No Content")} + ) + def delete(self, request, *args, **kwargs): + return super().delete(request, *args, **kwargs) + class TagListView(generics.ListCreateAPIView): queryset = Tag.objects.all() serializer_class = TagSerializer @@ -44,7 +86,7 @@ def perform_create(self, serializer): class BlogListCreateView(generics.ListCreateAPIView): queryset = Blog.objects.all() - serializer_class = BlogSerializer + serializer_class = BlogCreateUpdateSerializer def get_permissions(self): if self.request.method == 'POST': diff --git a/documentation/main.md b/documentation/main.md index 568ec97..118efdb 100644 --- a/documentation/main.md +++ b/documentation/main.md @@ -1 +1 @@ -The Django Cameroon main website API. \ No newline at end of file +The Django Cameroon main website API. diff --git a/website_api/settings/apps.py b/website_api/settings/apps.py index cd8878d..60d7b45 100644 --- a/website_api/settings/apps.py +++ b/website_api/settings/apps.py @@ -3,6 +3,10 @@ "rest_framework", "drf_yasg", "oauth2_provider", + + + + ] CUSTOM_APPS = [ diff --git a/website_api/settings/base.py b/website_api/settings/base.py index 852349c..32f57e9 100644 --- a/website_api/settings/base.py +++ b/website_api/settings/base.py @@ -37,6 +37,7 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + 'rest_framework.authtoken', From bf83027938e8fd3c670e1589ed70d4733ea00250 Mon Sep 17 00:00:00 2001 From: saahndongransom Date: Thu, 4 Jul 2024 06:23:07 +0100 Subject: [PATCH 03/13] blog app added --- .../pull_request_template.md | 1 + .github/pull_request_template.md | 1 + blog/serializers.py | 82 ++++++++++++++----- blog/views.py | 13 ++- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 1559f7e..f9fc5bb 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -13,3 +13,4 @@ Closes #23 ## Screenshots (Insert image, only for frontend) +Bearer d855f89533088ce049754df15432f411 \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1559f7e..ca2787a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,3 +13,4 @@ Closes #23 ## Screenshots (Insert image, only for frontend) +Bearer d855f89533088ce049754df15432f411 diff --git a/blog/serializers.py b/blog/serializers.py index 1e25b14..c2c8475 100644 --- a/blog/serializers.py +++ b/blog/serializers.py @@ -25,43 +25,85 @@ class BlogSerializer(serializers.ModelSerializer): author = AuthorSerializer() categories = CategorySerializer(many=True) tags = TagSerializer(many=True) - images = ImageSerializer(many=True, read_only=True) + images = ImageSerializer(many=True, read_only=True) class Meta: model = Blog - fields = ['author', 'categories', 'tags', 'title', 'content', 'images'] + fields = ['author', 'categories', 'tags', 'title', 'content', 'images'] def create(self, validated_data): author_data = validated_data.pop('author') categories_data = validated_data.pop('categories', []) tags_data = validated_data.pop('tags', []) - author_instance, _ = Author.objects.get_or_create(**author_data) - blog = Blog.objects.create(author=author_instance, **validated_data) - - if categories_data: - categories_instances = [ - Category.objects.get_or_create(**category_data)[0] - for category_data in categories_data - ] - blog.categories.add(*categories_instances) - - - if tags_data: - tags_instances = [ - Tag.objects.get_or_create(**tag_data)[0] - for tag_data in tags_data - ] - blog.tags.add(*tags_instances) + self._update_categories_and_tags(blog, categories_data, tags_data) return blog + def update(self, instance, validated_data): + author_data = validated_data.pop('author', None) + categories_data = validated_data.pop('categories', []) + tags_data = validated_data.pop('tags', []) + + if author_data: + author_instance, _ = Author.objects.get_or_create(**author_data) + instance.author = author_instance + + instance.title = validated_data.get('title', instance.title) + instance.content = validated_data.get('content', instance.content) + instance.save() + + self._update_categories_and_tags(instance, categories_data, tags_data) + + return instance + + def _update_categories_and_tags(self, instance, categories_data, tags_data): + # Update categories + updated_categories = [] + for category_data in categories_data: + category, _ = Category.objects.get_or_create(**category_data) + updated_categories.append(category) + instance.categories.set(updated_categories) + + # Update tags + updated_tags = [] + for tag_data in tags_data: + tag, _ = Tag.objects.get_or_create(**tag_data) + updated_tags.append(tag) + instance.tags.set(updated_tags) class BlogCreateUpdateSerializer(serializers.ModelSerializer): + author = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all()) + categories = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True) + tags = serializers.PrimaryKeyRelatedField(queryset=Tag.objects.all(), many=True) + class Meta: model = Blog - fields = '__all__' + fields = ['author', 'categories', 'tags', 'title', 'content'] + + def create(self, validated_data): + categories = validated_data.pop('categories') + tags = validated_data.pop('tags') + blog = Blog.objects.create(**validated_data) + blog.categories.set(categories) + blog.tags.set(tags) + return blog + + def update(self, instance, validated_data): + categories = validated_data.pop('categories', None) + tags = validated_data.pop('tags', None) + + for attr, value in validated_data.items(): + setattr(instance, attr, value) + + if categories is not None: + instance.categories.set(categories) + + if tags is not None: + instance.tags.set(tags) + instance.save() + return instance diff --git a/blog/views.py b/blog/views.py index 1f5b9fd..654de34 100644 --- a/blog/views.py +++ b/blog/views.py @@ -9,10 +9,13 @@ from django.http import HttpResponse from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi - class PostList(generics.ListCreateAPIView): queryset = Blog.objects.all() - serializer_class = BlogSerializer + + def get_serializer_class(self): + if self.request.method == 'POST': + return BlogCreateUpdateSerializer + return BlogSerializer def get_permissions(self): if self.request.method == 'POST': @@ -36,7 +39,11 @@ def post(self, request, *args, **kwargs): class PostDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Blog.objects.all() - serializer_class = BlogSerializer + + def get_serializer_class(self): + if self.request.method in ['PUT', 'PATCH']: + return BlogCreateUpdateSerializer + return BlogSerializer @swagger_auto_schema( operation_description="Retrieve a blog post", From 2af00363cd9f4338440b93be67a618ad57ce3900 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Thu, 26 Sep 2024 21:14:19 +0000 Subject: [PATCH 04/13] moved blog into apps --- {blog => apps/blog}/__init__.py | 0 {blog => apps/blog}/admin.py | 2 +- {blog => apps/blog}/apps.py | 0 {blog => apps/blog}/migrations/0001_initial.py | 0 {blog => apps/blog}/migrations/__init__.py | 0 {blog => apps/blog}/models.py | 0 {blog => apps/blog}/permissions.py | 0 {blog => apps/blog}/serializers.py | 2 +- {blog => apps/blog}/signals.py | 2 +- {blog => apps/blog}/tasks.py | 2 +- {blog => apps/blog}/tests.py | 2 +- {blog => apps/blog}/urls.py | 0 {blog => apps/blog}/views.py | 2 +- website_api/routes/main.py | 8 ++++---- website_api/settings/apps.py | 6 +----- 15 files changed, 11 insertions(+), 15 deletions(-) rename {blog => apps/blog}/__init__.py (100%) rename {blog => apps/blog}/admin.py (73%) rename {blog => apps/blog}/apps.py (100%) rename {blog => apps/blog}/migrations/0001_initial.py (100%) rename {blog => apps/blog}/migrations/__init__.py (100%) rename {blog => apps/blog}/models.py (100%) rename {blog => apps/blog}/permissions.py (100%) rename {blog => apps/blog}/serializers.py (98%) rename {blog => apps/blog}/signals.py (90%) rename {blog => apps/blog}/tasks.py (79%) rename {blog => apps/blog}/tests.py (80%) rename {blog => apps/blog}/urls.py (100%) rename {blog => apps/blog}/views.py (98%) diff --git a/blog/__init__.py b/apps/blog/__init__.py similarity index 100% rename from blog/__init__.py rename to apps/blog/__init__.py diff --git a/blog/admin.py b/apps/blog/admin.py similarity index 73% rename from blog/admin.py rename to apps/blog/admin.py index ec5d613..2b9ab03 100644 --- a/blog/admin.py +++ b/apps/blog/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Tag, Category, Author, Blog, Image +from .models.models import Tag, Category, Author, Blog, Image admin.site.register(Tag) admin.site.register(Category) diff --git a/blog/apps.py b/apps/blog/apps.py similarity index 100% rename from blog/apps.py rename to apps/blog/apps.py diff --git a/blog/migrations/0001_initial.py b/apps/blog/migrations/0001_initial.py similarity index 100% rename from blog/migrations/0001_initial.py rename to apps/blog/migrations/0001_initial.py diff --git a/blog/migrations/__init__.py b/apps/blog/migrations/__init__.py similarity index 100% rename from blog/migrations/__init__.py rename to apps/blog/migrations/__init__.py diff --git a/blog/models.py b/apps/blog/models.py similarity index 100% rename from blog/models.py rename to apps/blog/models.py diff --git a/blog/permissions.py b/apps/blog/permissions.py similarity index 100% rename from blog/permissions.py rename to apps/blog/permissions.py diff --git a/blog/serializers.py b/apps/blog/serializers.py similarity index 98% rename from blog/serializers.py rename to apps/blog/serializers.py index c2c8475..6bd9e95 100644 --- a/blog/serializers.py +++ b/apps/blog/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import Tag, Category, Author, Blog, Image +from .models.models import Tag, Category, Author, Blog, Image class TagSerializer(serializers.ModelSerializer): class Meta: diff --git a/blog/signals.py b/apps/blog/signals.py similarity index 90% rename from blog/signals.py rename to apps/blog/signals.py index 8fd879b..0ae46a0 100644 --- a/blog/signals.py +++ b/apps/blog/signals.py @@ -1,6 +1,6 @@ from django.db.models.signals import pre_delete from django.dispatch import receiver -from .models import Image +from .models.models import Image import os @receiver(pre_delete, sender=Image) diff --git a/blog/tasks.py b/apps/blog/tasks.py similarity index 79% rename from blog/tasks.py rename to apps/blog/tasks.py index 718d0e6..d0c32f7 100644 --- a/blog/tasks.py +++ b/apps/blog/tasks.py @@ -1,5 +1,5 @@ from celery import shared_task -from .models import Image +from .models.models import Image @shared_task def handle_image_upload(image_id): diff --git a/blog/tests.py b/apps/blog/tests.py similarity index 80% rename from blog/tests.py rename to apps/blog/tests.py index c881821..a2169b6 100644 --- a/blog/tests.py +++ b/apps/blog/tests.py @@ -1,6 +1,6 @@ from django.test import TestCase -from .models import Tag, Category, Author, Blog, Image +from .models.models import Tag, Category, Author, Blog, Image class TagModelTest(TestCase): def setUp(self): diff --git a/blog/urls.py b/apps/blog/urls.py similarity index 100% rename from blog/urls.py rename to apps/blog/urls.py diff --git a/blog/views.py b/apps/blog/views.py similarity index 98% rename from blog/views.py rename to apps/blog/views.py index 654de34..4bc495e 100644 --- a/blog/views.py +++ b/apps/blog/views.py @@ -1,5 +1,5 @@ from rest_framework import generics, permissions -from .models import Blog, Tag, Category, Author, Image +from .models.models import Blog, Tag, Category, Author, Image from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer diff --git a/website_api/routes/main.py b/website_api/routes/main.py index ade2a19..e4b2c98 100644 --- a/website_api/routes/main.py +++ b/website_api/routes/main.py @@ -44,15 +44,15 @@ name="schema-swagger-ui", ), path("admin/", admin.site.urls), + # Users app path(f"{BASE_API_URL}/", include("apps.users.routes.api")), + # Events app path(f"{BASE_API_URL}/", include("apps.events.routes.api")), - # Blog app - *blog_urls, - - + # Blog app + path(f"{BASE_API_URL}/", include("apps.blog.urls")) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/website_api/settings/apps.py b/website_api/settings/apps.py index 60d7b45..11b7c1e 100644 --- a/website_api/settings/apps.py +++ b/website_api/settings/apps.py @@ -3,14 +3,10 @@ "rest_framework", "drf_yasg", "oauth2_provider", - - - - ] CUSTOM_APPS = [ "apps.users", "apps.events", - "blog", + "apps.blog", ] From 2d0c137d2dfad4c404af6b98085bd3b99c29daf5 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Fri, 27 Sep 2024 03:32:54 +0000 Subject: [PATCH 05/13] fixes --- apps/blog/admin.py | 2 +- apps/blog/serializers.py | 2 +- apps/blog/signals.py | 2 +- apps/blog/tasks.py | 2 +- apps/blog/tests.py | 2 +- apps/blog/views.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/blog/admin.py b/apps/blog/admin.py index 2b9ab03..ec5d613 100644 --- a/apps/blog/admin.py +++ b/apps/blog/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models.models import Tag, Category, Author, Blog, Image +from .models import Tag, Category, Author, Blog, Image admin.site.register(Tag) admin.site.register(Category) diff --git a/apps/blog/serializers.py b/apps/blog/serializers.py index 6bd9e95..c2c8475 100644 --- a/apps/blog/serializers.py +++ b/apps/blog/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models.models import Tag, Category, Author, Blog, Image +from .models import Tag, Category, Author, Blog, Image class TagSerializer(serializers.ModelSerializer): class Meta: diff --git a/apps/blog/signals.py b/apps/blog/signals.py index 0ae46a0..8fd879b 100644 --- a/apps/blog/signals.py +++ b/apps/blog/signals.py @@ -1,6 +1,6 @@ from django.db.models.signals import pre_delete from django.dispatch import receiver -from .models.models import Image +from .models import Image import os @receiver(pre_delete, sender=Image) diff --git a/apps/blog/tasks.py b/apps/blog/tasks.py index d0c32f7..718d0e6 100644 --- a/apps/blog/tasks.py +++ b/apps/blog/tasks.py @@ -1,5 +1,5 @@ from celery import shared_task -from .models.models import Image +from .models import Image @shared_task def handle_image_upload(image_id): diff --git a/apps/blog/tests.py b/apps/blog/tests.py index a2169b6..c881821 100644 --- a/apps/blog/tests.py +++ b/apps/blog/tests.py @@ -1,6 +1,6 @@ from django.test import TestCase -from .models.models import Tag, Category, Author, Blog, Image +from .models import Tag, Category, Author, Blog, Image class TagModelTest(TestCase): def setUp(self): diff --git a/apps/blog/views.py b/apps/blog/views.py index 4bc495e..654de34 100644 --- a/apps/blog/views.py +++ b/apps/blog/views.py @@ -1,5 +1,5 @@ from rest_framework import generics, permissions -from .models.models import Blog, Tag, Category, Author, Image +from .models import Blog, Tag, Category, Author, Image from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer From c14c903ab07161d41bd81c72cbb15b14a9be45b6 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Sat, 28 Sep 2024 19:52:40 +0000 Subject: [PATCH 06/13] .venv --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 09f2680..3d2b97e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Ignore the virtual environment venv/ +.venv # Ignore the Django secret key secret_key.txt From 5afaf85b386795af1c979a45d071a13c30876dc1 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Sat, 28 Sep 2024 19:54:15 +0000 Subject: [PATCH 07/13] refactoring blog app --- apps/blog/admin.py | 6 ++- apps/blog/apps.py | 11 ++-- apps/blog/models.py | 41 --------------- apps/blog/models/__init__.py | 0 apps/blog/models/author.py | 12 +++++ apps/blog/models/blog.py | 19 +++++++ apps/blog/models/category.py | 9 ++++ apps/blog/models/image.py | 11 ++++ apps/blog/models/tag.py | 8 +++ apps/blog/routes/__init__.py | 0 apps/blog/routes/api.py | 9 ++++ apps/blog/serializers/__init__.py | 0 apps/blog/serializers/author_serializer.py | 8 +++ .../blog_serializer.py} | 30 ++++------- apps/blog/serializers/category_serializer.py | 7 +++ apps/blog/serializers/image_serializer.py | 7 +++ apps/blog/serializers/tag_serializer.py | 7 +++ apps/blog/signals.py | 2 +- apps/blog/test/__init__.py | 0 .../blog/{tests.py => test/test_tag_model.py} | 6 ++- apps/blog/urls.py | 8 --- apps/blog/views/__init__.py | 0 apps/blog/views/author | 7 +++ apps/blog/views/blog.py | 17 ++++++ apps/blog/views/category.py | 7 +++ apps/blog/views/image.py | 17 ++++++ apps/blog/views/index.py | 5 ++ apps/blog/{views.py => views/post.py} | 52 ++----------------- apps/blog/views/tag.py | 7 +++ apps/events/test/__init__.py | 3 +- apps/users/test/__init__.py | 3 +- 31 files changed, 190 insertions(+), 129 deletions(-) delete mode 100644 apps/blog/models.py create mode 100644 apps/blog/models/__init__.py create mode 100644 apps/blog/models/author.py create mode 100644 apps/blog/models/blog.py create mode 100644 apps/blog/models/category.py create mode 100644 apps/blog/models/image.py create mode 100644 apps/blog/models/tag.py create mode 100644 apps/blog/routes/__init__.py create mode 100644 apps/blog/routes/api.py create mode 100644 apps/blog/serializers/__init__.py create mode 100644 apps/blog/serializers/author_serializer.py rename apps/blog/{serializers.py => serializers/blog_serializer.py} (85%) create mode 100644 apps/blog/serializers/category_serializer.py create mode 100644 apps/blog/serializers/image_serializer.py create mode 100644 apps/blog/serializers/tag_serializer.py create mode 100644 apps/blog/test/__init__.py rename apps/blog/{tests.py => test/test_tag_model.py} (55%) delete mode 100644 apps/blog/urls.py create mode 100644 apps/blog/views/__init__.py create mode 100644 apps/blog/views/author create mode 100644 apps/blog/views/blog.py create mode 100644 apps/blog/views/category.py create mode 100644 apps/blog/views/image.py create mode 100644 apps/blog/views/index.py rename apps/blog/{views.py => views/post.py} (54%) create mode 100644 apps/blog/views/tag.py diff --git a/apps/blog/admin.py b/apps/blog/admin.py index ec5d613..6f2c072 100644 --- a/apps/blog/admin.py +++ b/apps/blog/admin.py @@ -1,5 +1,9 @@ from django.contrib import admin -from .models import Tag, Category, Author, Blog, Image +from apps.blog.models.tag import Tag +from apps.blog.models.category import Category +from apps.blog.models.author import Author +from apps.blog.models.blog import Blog +from apps.blog.models.image import Image admin.site.register(Tag) admin.site.register(Category) diff --git a/apps/blog/apps.py b/apps/blog/apps.py index c23d826..ece6ff5 100644 --- a/apps/blog/apps.py +++ b/apps/blog/apps.py @@ -1,15 +1,16 @@ from django.apps import AppConfig -class BlogConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'blog' +# class BlogConfig(AppConfig): +# default_auto_field = 'django.db.models.BigAutoField' +# name = 'blog' class BlogConfig(AppConfig): - name = 'blog' + name = 'apps.blog' + default_auto_field = 'django.db.models.BigAutoField' def ready(self): - import blog.signals + import apps.blog.signals diff --git a/apps/blog/models.py b/apps/blog/models.py deleted file mode 100644 index a1d58c2..0000000 --- a/apps/blog/models.py +++ /dev/null @@ -1,41 +0,0 @@ -from django.db import models - -class Tag(models.Model): - name = models.CharField(max_length=100) - - def __str__(self): - return self.name - -class Category(models.Model): - name = models.CharField(max_length=100) - - def __str__(self): - return self.name - -class Author(models.Model): - name = models.CharField(max_length=100) - bio = models.TextField() - - def __str__(self): - return self.name - -class Blog(models.Model): - title = models.CharField(max_length=200) - content = models.TextField() - created_at = models.DateTimeField(auto_now_add=True) - updated_at = models.DateTimeField(auto_now=True) - author = models.ForeignKey(Author, on_delete=models.CASCADE) - categories = models.ManyToManyField(Category) - tags = models.ManyToManyField(Tag) - - def __str__(self): - return self.title - -class Image(models.Model): - image_file = models.ImageField(upload_to='images/') - uploaded_at = models.DateTimeField(auto_now_add=True) - blog_post = models.ForeignKey(Blog, related_name='images', on_delete=models.CASCADE) - - def __str__(self): - return f"Image for {self.blog_post.title}" - diff --git a/apps/blog/models/__init__.py b/apps/blog/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/blog/models/author.py b/apps/blog/models/author.py new file mode 100644 index 0000000..3540a74 --- /dev/null +++ b/apps/blog/models/author.py @@ -0,0 +1,12 @@ +from django.db import models + + + +class Author(models.Model): + name = models.CharField(max_length=100) + bio = models.TextField() + + def __str__(self): + return self.name + + diff --git a/apps/blog/models/blog.py b/apps/blog/models/blog.py new file mode 100644 index 0000000..8300290 --- /dev/null +++ b/apps/blog/models/blog.py @@ -0,0 +1,19 @@ +from django.db import models +from apps.blog.models.author import Author +from apps.blog.models.tag import Tag +from apps.blog.models.category import Category + +class Blog(models.Model): + title = models.CharField(max_length=200) + content = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + author = models.ForeignKey(Author, on_delete=models.CASCADE) + categories = models.ManyToManyField(Category) + tags = models.ManyToManyField(Tag) + + def __str__(self): + return self.title + + + diff --git a/apps/blog/models/category.py b/apps/blog/models/category.py new file mode 100644 index 0000000..b95f7b3 --- /dev/null +++ b/apps/blog/models/category.py @@ -0,0 +1,9 @@ +from django.db import models + +class Category(models.Model): + name = models.CharField(max_length=100) + + def __str__(self): + return self.name + + diff --git a/apps/blog/models/image.py b/apps/blog/models/image.py new file mode 100644 index 0000000..33ef58a --- /dev/null +++ b/apps/blog/models/image.py @@ -0,0 +1,11 @@ +from django.db import models +from apps.blog.models.blog import Blog + +class Image(models.Model): + image_file = models.ImageField(upload_to='images/') + uploaded_at = models.DateTimeField(auto_now_add=True) + blog_post = models.ForeignKey(Blog, related_name='images', on_delete=models.CASCADE) + + def __str__(self): + return f"Image for {self.blog_post.title}" + diff --git a/apps/blog/models/tag.py b/apps/blog/models/tag.py new file mode 100644 index 0000000..67662d0 --- /dev/null +++ b/apps/blog/models/tag.py @@ -0,0 +1,8 @@ +from django.db import models + +class Tag(models.Model): + name = models.CharField(max_length=100) + + def __str__(self): + return self.name + \ No newline at end of file diff --git a/apps/blog/routes/__init__.py b/apps/blog/routes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/blog/routes/api.py b/apps/blog/routes/api.py new file mode 100644 index 0000000..1f17208 --- /dev/null +++ b/apps/blog/routes/api.py @@ -0,0 +1,9 @@ +from django.urls import path +from apps.blog.views.post import PostDetail,PostList +from apps.blog.views.blog import BlogListCreateView + +urlpatterns = [ + path('posts/', PostList.as_view(), name='post-list'), + path('posts//', PostDetail.as_view(), name='post-detail'), + path('posts/create/', BlogListCreateView.as_view(), name='post-create'), +] diff --git a/apps/blog/serializers/__init__.py b/apps/blog/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/blog/serializers/author_serializer.py b/apps/blog/serializers/author_serializer.py new file mode 100644 index 0000000..63f83a9 --- /dev/null +++ b/apps/blog/serializers/author_serializer.py @@ -0,0 +1,8 @@ +from rest_framework import serializers +from apps.blog.models.author import Author + + +class AuthorSerializer(serializers.ModelSerializer): + class Meta: + model = Author + fields = ('id', 'name', 'bio') diff --git a/apps/blog/serializers.py b/apps/blog/serializers/blog_serializer.py similarity index 85% rename from apps/blog/serializers.py rename to apps/blog/serializers/blog_serializer.py index c2c8475..d6dfb99 100644 --- a/apps/blog/serializers.py +++ b/apps/blog/serializers/blog_serializer.py @@ -1,25 +1,13 @@ from rest_framework import serializers -from .models import Tag, Category, Author, Blog, Image +from apps.blog.models.blog import Blog +from apps.blog.models.author import Author +from apps.blog.models.category import Category +from apps.blog.models.tag import Tag +from apps.blog.serializers.author_serializer import AuthorSerializer +from apps.blog.serializers.category_serializer import CategorySerializer +from apps.blog.serializers.tag_serializer import TagSerializer +from apps.blog.serializers.image_serializer import ImageSerializer -class TagSerializer(serializers.ModelSerializer): - class Meta: - model = Tag - fields = '__all__' - -class CategorySerializer(serializers.ModelSerializer): - class Meta: - model = Category - fields = '__all__' - -class AuthorSerializer(serializers.ModelSerializer): - class Meta: - model = Author - fields = ('id', 'name', 'bio') - -class ImageSerializer(serializers.ModelSerializer): - class Meta: - model = Image - fields = '__all__' class BlogSerializer(serializers.ModelSerializer): author = AuthorSerializer() @@ -75,6 +63,8 @@ def _update_categories_and_tags(self, instance, categories_data, tags_data): tag, _ = Tag.objects.get_or_create(**tag_data) updated_tags.append(tag) instance.tags.set(updated_tags) + + class BlogCreateUpdateSerializer(serializers.ModelSerializer): author = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all()) categories = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all(), many=True) diff --git a/apps/blog/serializers/category_serializer.py b/apps/blog/serializers/category_serializer.py new file mode 100644 index 0000000..7a88ac7 --- /dev/null +++ b/apps/blog/serializers/category_serializer.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from apps.blog.models.category import Category + +class CategorySerializer(serializers.ModelSerializer): + class Meta: + model = Category + fields = '__all__' \ No newline at end of file diff --git a/apps/blog/serializers/image_serializer.py b/apps/blog/serializers/image_serializer.py new file mode 100644 index 0000000..34e3fbf --- /dev/null +++ b/apps/blog/serializers/image_serializer.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from apps.blog.models.image import Image + +class ImageSerializer(serializers.ModelSerializer): + class Meta: + model = Image + fields = '__all__' diff --git a/apps/blog/serializers/tag_serializer.py b/apps/blog/serializers/tag_serializer.py new file mode 100644 index 0000000..3111c07 --- /dev/null +++ b/apps/blog/serializers/tag_serializer.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from apps.blog.models.tag import Tag + +class TagSerializer(serializers.ModelSerializer): + class Meta: + model = Tag + fields = '__all__' diff --git a/apps/blog/signals.py b/apps/blog/signals.py index 8fd879b..dd186bb 100644 --- a/apps/blog/signals.py +++ b/apps/blog/signals.py @@ -1,6 +1,6 @@ from django.db.models.signals import pre_delete from django.dispatch import receiver -from .models import Image +from apps.blog.models.image import Image import os @receiver(pre_delete, sender=Image) diff --git a/apps/blog/test/__init__.py b/apps/blog/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/blog/tests.py b/apps/blog/test/test_tag_model.py similarity index 55% rename from apps/blog/tests.py rename to apps/blog/test/test_tag_model.py index c881821..ebc982d 100644 --- a/apps/blog/tests.py +++ b/apps/blog/test/test_tag_model.py @@ -1,6 +1,10 @@ from django.test import TestCase -from .models import Tag, Category, Author, Blog, Image +from apps.blog.models.tag import Tag +from apps.blog.models.category import Category +from apps.blog.models.author import Author +from apps.blog.models.blog import Blog +from apps.blog.models.image import Image class TagModelTest(TestCase): def setUp(self): diff --git a/apps/blog/urls.py b/apps/blog/urls.py deleted file mode 100644 index 8d54abb..0000000 --- a/apps/blog/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.urls import path -from . import views - -urlpatterns = [ - path('posts/', views.PostList.as_view(), name='post-list'), - path('posts//', views.PostDetail.as_view(), name='post-detail'), - path('posts/create/', views.BlogListCreateView.as_view(), name='post-create'), -] diff --git a/apps/blog/views/__init__.py b/apps/blog/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/blog/views/author b/apps/blog/views/author new file mode 100644 index 0000000..70c7c82 --- /dev/null +++ b/apps/blog/views/author @@ -0,0 +1,7 @@ +from rest_framework import generics +from apps.blog.models.author import Author +from apps.blog.serializers.author_serializer import AuthorSerializer + +class AuthorListView(generics.ListCreateAPIView): + queryset = Author.objects.all() + serializer_class = AuthorSerializer diff --git a/apps/blog/views/blog.py b/apps/blog/views/blog.py new file mode 100644 index 0000000..461e24e --- /dev/null +++ b/apps/blog/views/blog.py @@ -0,0 +1,17 @@ +from rest_framework import generics, permissions +from apps.blog.models.blog import Blog +from apps.blog.serializers.blog_serializer import BlogSerializer, BlogCreateUpdateSerializer + + +class BlogListCreateView(generics.ListCreateAPIView): + queryset = Blog.objects.all() + serializer_class = BlogCreateUpdateSerializer + + def get_permissions(self): + if self.request.method == 'POST': + self.permission_classes = [permissions.IsAuthenticated] + return super().get_permissions() + +class BlogDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = Blog.objects.all() + serializer_class = BlogSerializer diff --git a/apps/blog/views/category.py b/apps/blog/views/category.py new file mode 100644 index 0000000..2c22d00 --- /dev/null +++ b/apps/blog/views/category.py @@ -0,0 +1,7 @@ +from rest_framework import generics +from apps.blog.models.category import Category +from apps.blog.serializers.category_serializer import CategorySerializer + +class CategoryListView(generics.ListCreateAPIView): + queryset = Category.objects.all() + serializer_class = CategorySerializer diff --git a/apps/blog/views/image.py b/apps/blog/views/image.py new file mode 100644 index 0000000..fafccb5 --- /dev/null +++ b/apps/blog/views/image.py @@ -0,0 +1,17 @@ +from rest_framework import generics +from apps.blog.models.image import Image +from apps.blog.serializers.image_serializer import ImageSerializer +from apps.blog.tasks import handle_image_upload + + +class ImageListView(generics.ListCreateAPIView): + queryset = Image.objects.all() + serializer_class = ImageSerializer + +class ImageCreateView(generics.CreateAPIView): + queryset = Image.objects.all() + serializer_class = ImageSerializer + + def perform_create(self, serializer): + instance = serializer.save() + handle_image_upload.delay(instance.id) diff --git a/apps/blog/views/index.py b/apps/blog/views/index.py new file mode 100644 index 0000000..bf607f4 --- /dev/null +++ b/apps/blog/views/index.py @@ -0,0 +1,5 @@ +from django.http import HttpResponse + + +def index(request): + return HttpResponse("Hello, world! This is the django cameroon page.") diff --git a/apps/blog/views.py b/apps/blog/views/post.py similarity index 54% rename from apps/blog/views.py rename to apps/blog/views/post.py index 654de34..1608631 100644 --- a/apps/blog/views.py +++ b/apps/blog/views/post.py @@ -1,14 +1,10 @@ from rest_framework import generics, permissions -from .models import Blog, Tag, Category, Author, Image -from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer - -from .serializers import BlogSerializer, BlogCreateUpdateSerializer, TagSerializer, CategorySerializer, AuthorSerializer, ImageSerializer - - -from .tasks import handle_image_upload -from django.http import HttpResponse +from apps.blog.models.blog import Blog +from apps.blog.serializers.blog_serializer import BlogSerializer, BlogCreateUpdateSerializer from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi + + class PostList(generics.ListCreateAPIView): queryset = Blog.objects.all() @@ -66,43 +62,3 @@ def put(self, request, *args, **kwargs): ) def delete(self, request, *args, **kwargs): return super().delete(request, *args, **kwargs) - -class TagListView(generics.ListCreateAPIView): - queryset = Tag.objects.all() - serializer_class = TagSerializer - -class CategoryListView(generics.ListCreateAPIView): - queryset = Category.objects.all() - serializer_class = CategorySerializer - -class AuthorListView(generics.ListCreateAPIView): - queryset = Author.objects.all() - serializer_class = AuthorSerializer - -class ImageListView(generics.ListCreateAPIView): - queryset = Image.objects.all() - serializer_class = ImageSerializer - -class ImageCreateView(generics.CreateAPIView): - queryset = Image.objects.all() - serializer_class = ImageSerializer - - def perform_create(self, serializer): - instance = serializer.save() - handle_image_upload.delay(instance.id) - -class BlogListCreateView(generics.ListCreateAPIView): - queryset = Blog.objects.all() - serializer_class = BlogCreateUpdateSerializer - - def get_permissions(self): - if self.request.method == 'POST': - self.permission_classes = [permissions.IsAuthenticated] - return super().get_permissions() - -class BlogDetail(generics.RetrieveUpdateDestroyAPIView): - queryset = Blog.objects.all() - serializer_class = BlogSerializer - -def index(request): - return HttpResponse("Hello, world! This is the django cameroon page.") diff --git a/apps/blog/views/tag.py b/apps/blog/views/tag.py new file mode 100644 index 0000000..94f2bbc --- /dev/null +++ b/apps/blog/views/tag.py @@ -0,0 +1,7 @@ +from rest_framework import generics +from apps.blog.models.tag import Tag +from apps.blog.serializers.tag_serializer import TagSerializer + +class TagListView(generics.ListCreateAPIView): + queryset = Tag.objects.all() + serializer_class = TagSerializer \ No newline at end of file diff --git a/apps/events/test/__init__.py b/apps/events/test/__init__.py index 971b955..46b134b 100644 --- a/apps/events/test/__init__.py +++ b/apps/events/test/__init__.py @@ -1,2 +1 @@ -ÿþ - +ÿþ \ No newline at end of file diff --git a/apps/users/test/__init__.py b/apps/users/test/__init__.py index 971b955..46b134b 100644 --- a/apps/users/test/__init__.py +++ b/apps/users/test/__init__.py @@ -1,2 +1 @@ -ÿþ - +ÿþ \ No newline at end of file From cdd05e787df49b7aac6bf4a1b3fb16a88833e312 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Thu, 3 Oct 2024 10:48:17 +0000 Subject: [PATCH 08/13] blog urls and ins --- website_api/routes/main.py | 14 +++++--------- website_api/settings/base.py | 4 +--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/website_api/routes/main.py b/website_api/routes/main.py index 44e146e..ac06922 100644 --- a/website_api/routes/main.py +++ b/website_api/routes/main.py @@ -7,22 +7,18 @@ from .swagger import urlpatterns as swagger_urlpatterns BASE_API_URL = "api/v1" -blog_urls = [ - path('blog/', include('blog.urls')), -] - urlpatterns = ( - [ - path("admin/", admin.site.urls), + [ path("admin/", admin.site.urls), path('__debug__/', include(debug_toolbar.urls)), path(f"{BASE_API_URL}/", include("apps.users.routes.api")), path(f"{BASE_API_URL}/", include("apps.events.routes.api")), path(f"{BASE_API_URL}/", include("apps.events.routes.extra")), - ] + swagger_urlpatterns - + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) - + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + path(f"{BASE_API_URL}/", include("apps.blog.routes.api")), + ] + swagger_urlpatterns + + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) ) handler404 = "apps.users.views.index.page_not_found_view" diff --git a/website_api/settings/base.py b/website_api/settings/base.py index cfe8d75..7f2c562 100644 --- a/website_api/settings/base.py +++ b/website_api/settings/base.py @@ -22,9 +22,7 @@ "django.contrib.messages", "django.contrib.staticfiles", 'rest_framework.authtoken', - - - + ] INSTALLED_APPS += THIRD_PARTY_APPS From db572966bf0beed9f1317affcdb27607855c0160 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Thu, 3 Oct 2024 10:48:38 +0000 Subject: [PATCH 09/13] adding missing routes --- apps/blog/routes/api.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/blog/routes/api.py b/apps/blog/routes/api.py index 1f17208..20c88d6 100644 --- a/apps/blog/routes/api.py +++ b/apps/blog/routes/api.py @@ -1,9 +1,21 @@ from django.urls import path -from apps.blog.views.post import PostDetail,PostList +from apps.blog.views.post import PostDetail, PostList from apps.blog.views.blog import BlogListCreateView +from apps.blog.views.author import AuthorListView +from apps.blog.views.category import CategoryListView +from apps.blog.views.image import ImageListView, ImageCreateView +from apps.blog.views.tag import TagListView +from apps.blog.views.index import index + urlpatterns = [ path('posts/', PostList.as_view(), name='post-list'), path('posts//', PostDetail.as_view(), name='post-detail'), path('posts/create/', BlogListCreateView.as_view(), name='post-create'), + path('authors/', AuthorListView.as_view(), name='author-list'), + path('categories/', CategoryListView.as_view(), name='category-list'), + path('images/', ImageListView.as_view(), name='image-list'), + path('images/create/', ImageCreateView.as_view(), name='image-create'), + path('tags/', TagListView.as_view(), name='tag-list'), + path('', index, name='index'), ] From 00f05ec42d6d0d383e306a84e788d986d96f11e7 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Fri, 4 Oct 2024 07:35:03 +0000 Subject: [PATCH 10/13] models inheriting from BaseModel --- apps/blog/models/author.py | 3 ++- apps/blog/models/blog.py | 3 ++- apps/blog/models/category.py | 3 ++- apps/blog/models/image.py | 3 ++- apps/blog/models/tag.py | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/blog/models/author.py b/apps/blog/models/author.py index 3540a74..8643288 100644 --- a/apps/blog/models/author.py +++ b/apps/blog/models/author.py @@ -1,8 +1,9 @@ from django.db import models +from apps.users.models.base_model import BaseModel -class Author(models.Model): +class Author(BaseModel): name = models.CharField(max_length=100) bio = models.TextField() diff --git a/apps/blog/models/blog.py b/apps/blog/models/blog.py index 8300290..f2dd627 100644 --- a/apps/blog/models/blog.py +++ b/apps/blog/models/blog.py @@ -1,9 +1,10 @@ from django.db import models +from apps.users.models.base_model import BaseModel from apps.blog.models.author import Author from apps.blog.models.tag import Tag from apps.blog.models.category import Category -class Blog(models.Model): +class Blog(BaseModel): title = models.CharField(max_length=200) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) diff --git a/apps/blog/models/category.py b/apps/blog/models/category.py index b95f7b3..8f51858 100644 --- a/apps/blog/models/category.py +++ b/apps/blog/models/category.py @@ -1,6 +1,7 @@ from django.db import models +from apps.users.models.base_model import BaseModel -class Category(models.Model): +class Category(BaseModel): name = models.CharField(max_length=100) def __str__(self): diff --git a/apps/blog/models/image.py b/apps/blog/models/image.py index 33ef58a..c36131b 100644 --- a/apps/blog/models/image.py +++ b/apps/blog/models/image.py @@ -1,7 +1,8 @@ from django.db import models +from apps.users.models.base_model import BaseModel from apps.blog.models.blog import Blog -class Image(models.Model): +class Image(BaseModel): image_file = models.ImageField(upload_to='images/') uploaded_at = models.DateTimeField(auto_now_add=True) blog_post = models.ForeignKey(Blog, related_name='images', on_delete=models.CASCADE) diff --git a/apps/blog/models/tag.py b/apps/blog/models/tag.py index 67662d0..a5f492f 100644 --- a/apps/blog/models/tag.py +++ b/apps/blog/models/tag.py @@ -1,6 +1,7 @@ from django.db import models +from apps.users.models.base_model import BaseModel -class Tag(models.Model): +class Tag(BaseModel): name = models.CharField(max_length=100) def __str__(self): From 3d3de61758aab55c337229a180a065d96a4df4d8 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Fri, 4 Oct 2024 07:35:20 +0000 Subject: [PATCH 11/13] added fileds to serializers --- apps/blog/serializers/category_serializer.py | 2 +- apps/blog/serializers/image_serializer.py | 2 +- apps/blog/tasks.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/blog/serializers/category_serializer.py b/apps/blog/serializers/category_serializer.py index 7a88ac7..cea16f9 100644 --- a/apps/blog/serializers/category_serializer.py +++ b/apps/blog/serializers/category_serializer.py @@ -4,4 +4,4 @@ class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category - fields = '__all__' \ No newline at end of file + fields = ["name"] \ No newline at end of file diff --git a/apps/blog/serializers/image_serializer.py b/apps/blog/serializers/image_serializer.py index 34e3fbf..484a88b 100644 --- a/apps/blog/serializers/image_serializer.py +++ b/apps/blog/serializers/image_serializer.py @@ -4,4 +4,4 @@ class ImageSerializer(serializers.ModelSerializer): class Meta: model = Image - fields = '__all__' + fields = ["image_file", "uploaded_at", "blog_post"] diff --git a/apps/blog/tasks.py b/apps/blog/tasks.py index 718d0e6..4f3bdbe 100644 --- a/apps/blog/tasks.py +++ b/apps/blog/tasks.py @@ -1,5 +1,5 @@ from celery import shared_task -from .models import Image +from apps.blog.models.image import Image @shared_task def handle_image_upload(image_id): From f36b0b03a727421cf71f8ce563fed3884d4d40c4 Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Fri, 4 Oct 2024 07:35:44 +0000 Subject: [PATCH 12/13] renamed file correctly --- apps/blog/views/author.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 apps/blog/views/author.py diff --git a/apps/blog/views/author.py b/apps/blog/views/author.py new file mode 100644 index 0000000..70c7c82 --- /dev/null +++ b/apps/blog/views/author.py @@ -0,0 +1,7 @@ +from rest_framework import generics +from apps.blog.models.author import Author +from apps.blog.serializers.author_serializer import AuthorSerializer + +class AuthorListView(generics.ListCreateAPIView): + queryset = Author.objects.all() + serializer_class = AuthorSerializer From cfc37f4f451a7e82284e741084bdd1e4e40a124f Mon Sep 17 00:00:00 2001 From: Johanan Oppong Amoateng Date: Fri, 4 Oct 2024 08:25:41 +0000 Subject: [PATCH 13/13] migrations --- ...r_created_at_author_created_by_and_more.py | 162 ++++++++++++++++++ apps/blog/views/author | 7 - ...basemodel_id_alter_eventtag_id_and_more.py | 28 --- 3 files changed, 162 insertions(+), 35 deletions(-) create mode 100644 apps/blog/migrations/0002_author_active_author_created_at_author_created_by_and_more.py delete mode 100644 apps/blog/views/author delete mode 100644 apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py diff --git a/apps/blog/migrations/0002_author_active_author_created_at_author_created_by_and_more.py b/apps/blog/migrations/0002_author_active_author_created_at_author_created_by_and_more.py new file mode 100644 index 0000000..9f07ddd --- /dev/null +++ b/apps/blog/migrations/0002_author_active_author_created_at_author_created_by_and_more.py @@ -0,0 +1,162 @@ +# Generated by Django 5.0.1 on 2024-10-04 08:17 + +import django.db.models.deletion +import django.utils.timezone +import utils.main +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='author', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='author', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='author', + name='created_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='author', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name='author', + name='updated_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='blog', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='blog', + name='created_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='blog', + name='updated_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='category', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='category', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='category', + name='created_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='category', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name='category', + name='updated_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='image', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='image', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='image', + name='created_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='image', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name='image', + name='updated_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='tag', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='tag', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='tag', + name='created_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='tag', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name='tag', + name='updated_by', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_%(class)s_set', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='author', + name='id', + field=models.UUIDField(default=utils.main.generate_uuid, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='blog', + name='id', + field=models.UUIDField(default=utils.main.generate_uuid, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='category', + name='id', + field=models.UUIDField(default=utils.main.generate_uuid, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='image', + name='id', + field=models.UUIDField(default=utils.main.generate_uuid, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='tag', + name='id', + field=models.UUIDField(default=utils.main.generate_uuid, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False), + ), + ] diff --git a/apps/blog/views/author b/apps/blog/views/author deleted file mode 100644 index 70c7c82..0000000 --- a/apps/blog/views/author +++ /dev/null @@ -1,7 +0,0 @@ -from rest_framework import generics -from apps.blog.models.author import Author -from apps.blog.serializers.author_serializer import AuthorSerializer - -class AuthorListView(generics.ListCreateAPIView): - queryset = Author.objects.all() - serializer_class = AuthorSerializer diff --git a/apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py b/apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py deleted file mode 100644 index 770e13c..0000000 --- a/apps/events/migrations/0003_alter_basemodel_id_alter_eventtag_id_and_more.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 5.0.1 on 2024-06-05 23:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('events', '0002_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='basemodel', - name='id', - field=models.UUIDField(default='4a458960-23ae-4d4d-82cf-b3c783fbb0a5', editable=False, help_text='Unique identifier for this object.', primary_key=True, serialize=False, verbose_name='id'), - ), - migrations.AlterField( - model_name='eventtag', - name='id', - field=models.UUIDField(default='92676ed1-ff1b-401b-aa3e-a380daa5f5f4', editable=False, help_text='Unique identifier for this object.', primary_key=True, serialize=False, verbose_name='id'), - ), - migrations.AlterField( - model_name='speaker', - name='id', - field=models.UUIDField(default='eecf61d8-aa9a-4bd9-8f10-34ba5be2158d', editable=False, help_text='Unique identifier for this object.', primary_key=True, serialize=False, verbose_name='id'), - ), - ]