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 기능을 추가했습니다.

apps.py

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

exceptions.py

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'"

pagination.py

from rest_framework.pagination import PageNumberPagination

class ArticlePagination(PageNumberPagination):
    page_size = 5

models.py

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}"

Did you find this article valuable?

Support Fullstack Developer at Your Service by becoming a sponsor. Any amount is appreciated!