8.[drf] 메인 앱 만들기
기본앱
- 구조를 보기 위한 예시로 앱을 만들어보겠습니다.
다른 종류의 앱을 만든다고 해도 구조를 참고할 수 있습니다.
앱은 다음과 같이 생성 가능합니다:
python manage.py startapp articles
python manage.py startapp ratings
python manage.py startapp favorites
python manage.py startapp reactions
python manage.py startapp search
python manage.py startapp comments
메인 블로그
- 블로그에 읽은 시간을 표현해주는 기능을 추가해보겠습니다.
블로그 만들 때 유용한 기능입니다.
커스텀 exception과 pagination 기능을 추가했습니다.
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class ArticlesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'articles'
verbose_name = _("Articles")
articles/real_time_engine.py
class ArticleReadTimeEngine:
def __init__(self, article):
self.article = article
self.words_per_minute = 250
self.banner_image_adjustment_time = round(1 / 6, 3)
def check_article_has_banner_image(self):
has_banner_image = True
if not self.article.banner_image:
has_banner_image = False
self.banner_image_adjustment_time = 0
return has_banner_image
def get_title(self):
return self.article.title
def get_tags(self):
tag_words = []
[tag_words.extends(tag_word.split()) for tag_word in self.article.tags ]
return tag_words
def get_body(self):
return self.article.body
def get_description(self):
return self.article.description
def get_article_details(self):
details = []
details.extend(self.get_title().split())
details.extend(self.get_body().split())
details.extend(self.get_description().split())
details.extend(self.get_tags().split())
return details
def get_read_time(self):
word_length = len(self.article.get_article_details())
read_time = 0
self.check_article_has_banner_image()
if word_length:
time_to_read = word_length / self.words_per_minute
if time_to_read < 1:
read_time = (
str(round((time_to_read + self.banner_image_adjustment_time)* 60)) + " second(s)"
)
else:
read_time = (
str(round(time_to_read + self.banner_image_adjustment_time))
+ " minute(s)")
return read_time
from rest_framework.exceptions import APIException
class UpdateArticle(APIException):
status_code = 403
default_detail = "You can't update an article that does not belong to you'"
from rest_framework.pagination import PageNumberPagination
class ArticlePagination(PageNumberPagination):
page_size = 5
from django.contrib.auth import get_user_model
from django.db import models
from django.utils.translation import gettext_lazy as _
from common.models import TimeStampedUUIDModel
User = get_user_model()
class Tag(TimeStampedUUIDModel):
class Range(models.IntegerChoices):
RATING_1 = 1,_("poor")
RATING_2 = 2,_("fair")
RATING_3 = 3,_("good")
RATING_4 = 4,_("very good")
RATING_5 = 5,_("excellent")
article = models.ForeignKey("articles.Article", related_name="article_ratings", on_delete=models.CASCADE)
rated_by = models.ForeignKey(User, related_name = "user_who_rated", on_delete=models.CASCADE)
value = models.IntegerField(
verbose_name=_("rating value"),
choices = Range.choices,
default = 0,
help_text = "1=Poor, 2=Fair, 3=Good, 4=Very Good, 5=Excellent"
)
review.models.TextField(verbose_name=_("rating review"), blank=True)
class Meta:
unique_together = ["rated_by", "article"]
def __str__(self):
return f"{self.article.title} rated at {self.value}"