-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(calendar): add model, viewset, serializer
- Loading branch information
Showing
12 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.contrib import admin | ||
|
||
# Register your models here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class CalendarConfig(AppConfig): | ||
default_auto_field = "django.db.models.BigAutoField" | ||
name = "Calendar" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from django.db import models | ||
|
||
from ara.db.models import MetaDataModel | ||
|
||
|
||
class Calendar(MetaDataModel): | ||
tag = models.ForeignKey( | ||
verbose_name="태그", | ||
to="core.Tag", | ||
on_delete=models.CASCADE, | ||
related_name="event_set", | ||
db_index=True, | ||
) | ||
is_allday = models.BooleanField( | ||
verbose_name="하루종일", | ||
default=False, | ||
) | ||
start_at = models.DateTimeField( | ||
verbose_name="시작 시간", | ||
blank=True, | ||
null=True, | ||
default=None, | ||
) | ||
end_at = models.DateTimeField( | ||
verbose_name="종료 시간", | ||
blank=True, | ||
null=True, | ||
default=None, | ||
) | ||
title = models.CharField( | ||
verbose_name="제목", | ||
max_length=512, | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
from Calendar.models import Calendar | ||
from rest_framework import serializers | ||
|
||
|
||
class CalendarSerializer(serializers.ModelSerializer): | ||
class Meta: | ||
model = Calendar | ||
fields = "__all__" | ||
|
||
|
||
from dateutil.relativedelta import relativedelta | ||
from django.utils import timezone | ||
from django.utils.translation import gettext | ||
from rest_framework import serializers | ||
|
||
from apps.user.models import UserProfile | ||
from ara.classes.serializers import MetaDataModelSerializer | ||
|
||
|
||
class UserProfileSerializer(MetaDataModelSerializer): | ||
... | ||
|
||
|
||
class UserProfileUpdateActionSerializer(MetaDataModelSerializer): | ||
class Meta(MetaDataModelSerializer.Meta): | ||
read_only_fields = ( | ||
"sid", | ||
"user", | ||
) | ||
|
||
def validate_nickname(self, value) -> str: | ||
nickname_changed = self.instance and value != self.instance.nickname | ||
if nickname_changed and not self.instance.can_change_nickname(): | ||
next_change_date = self.instance.nickname_updated_at + relativedelta( | ||
months=3 | ||
) | ||
raise serializers.ValidationError( | ||
gettext( | ||
"Nicknames can only be changed every 3 months. (can't change until %(date)s)" | ||
) | ||
% {"date": next_change_date.strftime("%Y/%m/%d")} | ||
) | ||
return value | ||
|
||
def update(self, instance, validated_data): | ||
new_nickname = validated_data.get("nickname") | ||
old_nickname = instance.nickname if instance else None | ||
if instance and new_nickname and old_nickname != new_nickname: | ||
validated_data["nickname_updated_at"] = timezone.now() | ||
return super(BaseUserProfileSerializer, self).update(instance, validated_data) | ||
|
||
|
||
class PublicUserProfileSerializer(BaseUserProfileSerializer): | ||
class Meta(BaseUserProfileSerializer.Meta): | ||
fields = ( | ||
"picture", | ||
"nickname", | ||
"user", | ||
"is_official", | ||
"is_school_admin", | ||
) | ||
|
||
|
||
class MyPageUserProfileSerializer(BaseUserProfileSerializer): | ||
num_articles = serializers.SerializerMethodField() | ||
num_comments = serializers.SerializerMethodField() | ||
num_positive_votes = serializers.SerializerMethodField() | ||
|
||
@staticmethod | ||
def get_num_articles(obj): | ||
from apps.core.models import Article | ||
|
||
num_articles = Article.objects.filter(created_by=obj.user).count() | ||
return num_articles | ||
|
||
@staticmethod | ||
def get_num_comments(obj): | ||
from apps.core.models import Comment | ||
|
||
num_comments = Comment.objects.filter(created_by=obj.user).count() | ||
return num_comments | ||
|
||
@staticmethod | ||
def get_num_positive_votes(obj): | ||
from apps.core.models import Vote | ||
|
||
num_article_votes = Vote.objects.filter( | ||
parent_article__created_by=obj.user, is_positive=True | ||
).count() | ||
num_comment_votes = Vote.objects.filter( | ||
parent_comment__created_by=obj.user, is_positive=True | ||
).count() | ||
return num_article_votes + num_comment_votes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.test import TestCase | ||
|
||
# Create your tests here. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .calendar import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from django.utils import timezone | ||
from rest_framework import decorators, mixins, response, status | ||
|
||
from apps.user.models import UserProfile | ||
from apps.user.permissions.user_profile import UserProfilePermission | ||
from apps.user.serializers.user_profile import ( | ||
PublicUserProfileSerializer, | ||
UserProfileSerializer, | ||
UserProfileUpdateActionSerializer, | ||
) | ||
from ara.classes.viewset import ActionAPIViewSet | ||
|
||
|
||
class CalendarViewSet( | ||
mixins.RetrieveModelMixin, mixins.UpdateModelMixin, ActionAPIViewSet | ||
): | ||
queryset = UserProfile.objects.all() | ||
serializer_class = UserProfileSerializer | ||
action_serializer_class = { | ||
"update": UserProfileUpdateActionSerializer, | ||
"partial_update": UserProfileUpdateActionSerializer, | ||
} | ||
permission_classes = (UserProfilePermission,) | ||
|
||
def retrieve(self, request, *args, **kwargs): | ||
profile = self.get_object() | ||
if request.user == profile.user: | ||
return super().retrieve(request, *args, **kwargs) | ||
else: | ||
return response.Response(PublicUserProfileSerializer(profile).data) | ||
|
||
@decorators.action(detail=True, methods=["patch"]) | ||
def agree_terms_of_service(self, request, *args, **kwargs): | ||
# BAD_REQUEST if user already agree with the terms of service | ||
if request.user.profile.agree_terms_of_service_at is not None: | ||
return response.Response( | ||
status=status.HTTP_400_BAD_REQUEST, | ||
) | ||
|
||
request.user.profile.agree_terms_of_service_at = timezone.now() | ||
request.user.profile.save() | ||
|
||
return response.Response( | ||
status=status.HTTP_200_OK, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from django.utils import timezone | ||
from rest_framework import decorators, mixins, response, status | ||
|
||
from apps.user.models import UserProfile | ||
from apps.user.permissions.user_profile import UserProfilePermission | ||
from apps.user.serializers.user_profile import ( | ||
PublicUserProfileSerializer, | ||
UserProfileSerializer, | ||
UserProfileUpdateActionSerializer, | ||
) | ||
from ara.classes.viewset import ActionAPIViewSet | ||
|
||
|
||
class UserProfileViewSet( | ||
mixins.RetrieveModelMixin, mixins.UpdateModelMixin, ActionAPIViewSet | ||
): | ||
queryset = UserProfile.objects.all() | ||
serializer_class = UserProfileSerializer | ||
action_serializer_class = { | ||
"update": UserProfileUpdateActionSerializer, | ||
"partial_update": UserProfileUpdateActionSerializer, | ||
} | ||
permission_classes = (UserProfilePermission,) | ||
|
||
def retrieve(self, request, *args, **kwargs): | ||
profile = self.get_object() | ||
if request.user == profile.user: | ||
return super().retrieve(request, *args, **kwargs) | ||
else: | ||
return response.Response(PublicUserProfileSerializer(profile).data) | ||
|
||
@decorators.action(detail=True, methods=["patch"]) | ||
def agree_terms_of_service(self, request, *args, **kwargs): | ||
# BAD_REQUEST if user already agree with the terms of service | ||
if request.user.profile.agree_terms_of_service_at is not None: | ||
return response.Response( | ||
status=status.HTTP_400_BAD_REQUEST, | ||
) | ||
|
||
request.user.profile.agree_terms_of_service_at = timezone.now() | ||
request.user.profile.save() | ||
|
||
return response.Response( | ||
status=status.HTTP_200_OK, | ||
) |