Skip to content

Commit

Permalink
refactor: crate comment app and integrate django_ltree_2
Browse files Browse the repository at this point in the history
  • Loading branch information
moonlitgrace committed Dec 13, 2024
1 parent bc7f8d7 commit 94d793b
Show file tree
Hide file tree
Showing 24 changed files with 386 additions and 92 deletions.
Empty file.
11 changes: 11 additions & 0 deletions backend/apps/comment/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.contrib import admin

from .models import Comment

# Register your models here.


@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('quibbler', 'content', 'created_at')
search_fields = ('quibbler__username', 'content')
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions backend/apps/comment/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class CommentConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.comment'
73 changes: 73 additions & 0 deletions backend/apps/comment/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Generated by Django 5.1.4 on 2024-12-13 10:36

import django.contrib.postgres.indexes
import django.db.models.deletion
import django_ltree.fields
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
('user', '0003_alter_profile_username'),
]

operations = [
migrations.CreateModel(
name='Comment',
fields=[
(
'id',
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name='ID',
),
),
(
'created_at',
models.DateTimeField(auto_now_add=True, verbose_name='create at'),
),
('path', django_ltree.fields.PathField(unique=True)),
('content', models.TextField(verbose_name='content')),
(
'downvotes',
models.ManyToManyField(
blank=True,
related_name='downvotes',
to='user.profile',
verbose_name='downvotes',
),
),
(
'quibbler',
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to='user.profile',
verbose_name='quibbler',
),
),
(
'upvotes',
models.ManyToManyField(
blank=True,
related_name='upvotes',
to='user.profile',
verbose_name='upvotes',
),
),
],
options={
'verbose_name': 'Comment',
'verbose_name_plural': 'Comments',
'indexes': [
django.contrib.postgres.indexes.GistIndex(
fields=['path'], name='comment_com_path_d1388c_gist'
)
],
},
),
]
Empty file.
34 changes: 34 additions & 0 deletions backend/apps/comment/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from django.contrib.postgres import indexes as idx
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_ltree.models import TreeModel

from apps.user.models import Profile
from common.mixins.model_mixins import CreatedAtMixin

# Create your models here.


class Comment(CreatedAtMixin, TreeModel):
quibbler = models.ForeignKey(
Profile, on_delete=models.CASCADE, verbose_name=_('quibbler')
)
content = models.TextField(_('content'))
upvotes = models.ManyToManyField(
Profile, related_name='upvotes', blank=True, verbose_name=_('upvotes')
)
downvotes = models.ManyToManyField(
Profile, related_name='downvotes', blank=True, verbose_name=_('downvotes')
)

@property
def children_count(self):
return self.children().count()

def __str__(self) -> str:
return f"Comment by {self.quibbler.username}"

class Meta: # pyright: ignore
indexes = [idx.GistIndex(fields=['path'])]
verbose_name = 'Comment'
verbose_name_plural = 'Comments'
16 changes: 16 additions & 0 deletions backend/apps/quiblet/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,23 @@ def validate_name(self, name):
return name


class QuibletSlimSerializer(ModelSerializer):
class Meta:
model = Quiblet
fields = ('name', 'avatar')


class QuibSerializer(ModelSerializer):
quiblet = QuibletSerializer(read_only=True)

class Meta:
model = Quib
fields = '__all__'


class QuibSlimSerializer(ModelSerializer):
quiblet = QuibletSlimSerializer(read_only=True)

class Meta:
model = Quib
exclude = ('quibber',)
8 changes: 6 additions & 2 deletions backend/apps/quiblet/api/v1/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from common.patches.request import PatchedHttpRequest

from ...models import Quib, Quiblet
from .serializers import QuibletSerializer, QuibSerializer
from .serializers import QuibletSerializer, QuibSerializer, QuibSlimSerializer


@extend_schema(tags=['quibs & quiblets'])
Expand All @@ -28,4 +28,8 @@ def perform_create(self, serializer):
@extend_schema(tags=['quibs & quiblets'])
class QuibViewSet(ModelViewSet):
queryset = Quib.objects.all()
serializer_class = QuibSerializer

def get_serializer_class(self): # pyright: ignore
if self.action == 'list':
return QuibSlimSerializer
return QuibSerializer
26 changes: 26 additions & 0 deletions backend/apps/quiblet/migrations/0003_quib_cover.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 5.1.4 on 2024-12-13 02:45

import dynamic_filenames
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('quiblet', '0002_initial'),
]

operations = [
migrations.AddField(
model_name='quib',
name='cover',
field=models.ImageField(
blank=True,
null=True,
upload_to=dynamic_filenames.FilePattern(
filename_pattern='cover/{uuid:s}{ext}'
),
verbose_name='cover',
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Generated by Django 5.1.4 on 2024-12-13 10:36

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('comment', '0001_initial'),
('quiblet', '0003_quib_cover'),
('user', '0003_alter_profile_username'),
]

operations = [
migrations.RemoveField(
model_name='quib',
name='dislikes',
),
migrations.RemoveField(
model_name='quib',
name='likes',
),
migrations.AddField(
model_name='quib',
name='comments',
field=models.ManyToManyField(
blank=True,
related_name='comments',
to='comment.comment',
verbose_name='comments',
),
),
migrations.AddField(
model_name='quib',
name='downvotes',
field=models.ManyToManyField(
blank=True,
related_name='downvoted_quibs',
to='user.profile',
verbose_name='downvotes',
),
),
migrations.AddField(
model_name='quib',
name='upvotes',
field=models.ManyToManyField(
blank=True,
related_name='upvoted_quibs',
to='user.profile',
verbose_name='upvotes',
),
),
]
24 changes: 19 additions & 5 deletions backend/apps/quiblet/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.utils.translation import gettext_lazy as _
from dynamic_filenames import FilePattern

from apps.comment.models import Comment
from apps.user.models import Profile
from common.mixins.model_mixins import (
AvatarMixin,
Expand All @@ -13,13 +14,17 @@
ShortUUIDMixin,
)

cover_file_pattern = FilePattern(filename_pattern="cover/{uuid:s}{ext}")

# models


class Quiblet(AvatarMixin, CreatedAtMixin, IsPublicMixin):
name = models.CharField(_('name'), unique=True, max_length=25)
description = models.TextField(_('description'))
cover = models.ImageField(
_('cover'),
upload_to=FilePattern(filename_pattern="cover/{uuid:s}{ext}"),
upload_to=cover_file_pattern,
blank=True,
null=True,
)
Expand Down Expand Up @@ -58,11 +63,20 @@ class Quib(CreatedAtMixin, IsPublicMixin, ShortUUIDMixin):
title = models.CharField(_('title'), max_length=255)
slug = models.SlugField(_('slug'), editable=False, max_length=25, blank=True)
content = models.TextField(_('content'))
likes = models.ManyToManyField(
Profile, related_name='liked_quibs', blank=True, verbose_name=_('likes')
cover = models.ImageField(
_('cover'),
upload_to=cover_file_pattern,
blank=True,
null=True,
)
upvotes = models.ManyToManyField(
Profile, related_name='upvoted_quibs', blank=True, verbose_name=_('upvotes')
)
downvotes = models.ManyToManyField(
Profile, related_name='downvoted_quibs', blank=True, verbose_name=_('downvotes')
)
dislikes = models.ManyToManyField(
Profile, related_name='disliked_quibs', blank=True, verbose_name=_('dislikes')
comments = models.ManyToManyField(
Comment, related_name='comments', blank=True, verbose_name=_('comments')
)

def save(self, *args, **kwargs):
Expand Down
3 changes: 3 additions & 0 deletions backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@
'drf_standardized_errors',
# file middleware
'django_cleanup',
# postgres ltree
'django_ltree',
]

SELF_APPS = [
'apps.user',
'apps.quiblet',
'apps.comment',
]

INSTALLED_APPS = DEFAULT_APPS + THIRD_PARTY_APPS + SELF_APPS
Expand Down
42 changes: 40 additions & 2 deletions backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ drf-spectacular = {extras = ["sidecar"], version = "^0.28.0"}
shortuuid = "^1.0.13"
# 3rd party exception handler
drf-standardized-errors = {extras = ["openapi"], version = "^0.14.1"}
django-ltree-2 = "^0.1.10"

[tool.poetry.group.dev.dependencies]
# task runner
Expand Down
Loading

0 comments on commit 94d793b

Please sign in to comment.