□ Model 필드 부분 update
포스트 방문 수 측정을 위해 Post 모델의 hits라는 필드를 가지고 있다.
class Post(models.Model):
...
hits = models.BigIntegerField(default=0)
updated_at = models.DateTimeField(auto_now=True)
...
정말 많은 사람들이 방문하고 그랬다면 Redis 서버를 별도로 두어서 카운팅을 하고 스케줄러를 통해 주기적으로 DB에 업데이트해줬을 것이지만 여기서는 그런 주제의 글이 아니기에 패쓰
단순하게 사람들이 방문하면 +1씩 값을 증가시켜주는데 아래와 같이 그냥 save를 호출할 경우, DB에 전체 필드를 그대로 업데이트하게 된다.
def retrieve(self, request, slug=None):
post = get_object_or_404(
Post.public.select_related("author"),
slug=slug,
)
post.hits += 1
post.save() # 방문수 +1 증가 후 저장
...
이는 불필요한 자원 소모를 가져오기 때문에 save를 호출할 때, update_fields를 명시해주면 해당 부분만 Update를 하게 된다.
참고로 여기서 updated_at 같은 수정일 관련 필드에서 auto_now가 true인 값을 가질 경우, udpate_fields에 같이 명시를 해주어야한다. 그렇지 않으면 수정일이 업데이트되지 않는다.
def retrieve(self, request, slug=None):
post = get_object_or_404(
Post.public.select_related("author"),
slug=slug,
)
post.hits += 1
post.save(update_fields=["hits", "updated_at"]) # 업데이트할 필드 명시
...
□ Model Manager
블로그 글을 작성할 때는 Django Admin에서 하기 때문에 공통적으로 코드 대부분이 발행된 글을 가지고 필터링하고 보여주는 것들이 대부분이다. 다시 말해 is_published 값이 True인 것들만 가지고 리스트를 보여주고 필터링한다.
class Post(models.Model):
...
is_published = models.BooleanField(default=False) # 글 발행 여부
...
ORM 가지고 매번 Post.objects.filter(is_published=True, ...) 이렇게 치면 너무 귀찮고 실수가 유발할 가능성이 커진다.
예를 들어 아래와 같이 각 상세 페이지에서는 이전, 다음 블로그 글의 제목을 표기해주는데 미발행 글을 고려하지 않으면 해당 글의 제목이 나타날 수 있다.
그래서 아래와 같이 매니저를 하나 만들어줬다. 별도로 명시하지 않으면 is_published 필드가 자동으로 True로 잡히고 혹시라도 누군가 is_published 필드를 False 이용하는 사태가 발생하면 그대로 사용할 수 있게 해주었다.
class PublicPostManager(models.Manager):
def filter(self, *args, **kwargs):
if kwargs.get("is_published") == False:
return super().get_queryset().filter(*args, **kwargs)
return self.get_queryset().filter(*args, **kwargs)
def get_queryset(self):
return super().get_queryset().filter(is_published=True)
처음에는 아래와 같이 objects를 오버라이드하여 사용하였었다. 내가 작성한 코드에서는 별문제가 없었으나..
class Post(models.Model):
...
objects = PublicPostManager()
근데 역시.. Django는 최대한 그대로 사용하는 것이 좋다는 것이 이런 부분에서 나타나는 것 같다. 이렇게 적용하게 되면 Django Admin의 Post 페이지에서는 is_published 필드가 True인 것만 나타나게 된다.
이에 따라 별도로 커스텀 매니저를 넣어주고 기존 것(objects)도 함께 넣어준다. 기존 것을 안넣어주면 Post.objects는 동작하지 않는다.
class Post(models.Model):
...
objects = models.Manager()
public = PublicPostManager()
'Project > [Project] React DRF Blog' 카테고리의 다른 글
[Frontend] 정리 - 1 (0) | 2023.06.29 |
---|---|
Intro. (0) | 2023.06.29 |