본문 바로가기
개발/Django_python 웹 프레임워크

Django - N:M 좋아요기능(Ajax 사용 X)

by 자유로운 코끼리 2020. 8. 3.
728x90

오늘은 좋아요 기능을 만들어 볼 거에요.

좋하요 기능의 경우 한명의 유저가 여러 게시물에 좋아요를 누를 수 있고,

또 하나의 게시물에 여러명의 유저가 좋아요를 누를 수 있어야겠죠?

그래서 데이터베이스 간에 다대다(N:M) 관계 설정이 필요합니다.

 

Models.py

class Post(models.Model): 
    user = models.ForeignKey(User,on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    body = models.TextField()
		# user model과 M:M 관계를 가지는 field 입니다.
    like = models.ManyToManyField(User, related_name='likes',blank=True)
    like_count = models.PositiveIntegerField(default=0) #0또는 양수만 받는 필드

N:M 관계를 위해 ManyToManyField를 사용하였습니다.

ManyToManyField 에 첫번째 인자에는 관계되는 모델을 입력합니다.

그리고 related_name 속성은, 첫번째 인자에서 접근할 때 사용하는 변수명을 의미합니다.

  • User ->  User.likes

blank=True는 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용합니다. 

유효성 검사와 관련있는 것으로 form.is_vaild()가 호출될 때 폼 유효성 검사에 사용되어집니다.

* null =True는 DB와 관련이 있는데, 주어진 db 컬럼 값이 null(정보없음)을 가질 것인지 아닌지를 정의합니다.

이때 CharFields()와 TextFields()에서는 예외로, NULL을 저장하지 않으며, 빈 값을 빈 문자열('')로 저장합니다.

 

마지막으로 like_count 에 쓰인 PositiveIntegerField는 0또는 양수만 받는 필드입니다.

 

views.py

def likes(request, blog_id):
    like_b = get_object_or_404(Blogapp, id=blog_id)
    if request.user in like_b.like.all():
        like_b.like.remove(request.user)
        like_b.like_count -= 1
        like_b.save()
    else:
        like_b.like.add(request.user)
        like_b.like_count += 1
        like_b.save()
    return redirect('/blog/detail/' + str(blog_id))

해당 id 값을 가진 객체의 like를 가지고 와서, 현재 유저가 포함되어 있다면(좋아요를 눌렀다면),

like 안에서 유저를 제외시키고, like_count의 숫자를 증가시켜 저장합니다.

또 그 반대의 상황이라면 유저를 추가하는 코드입니다.

 

urls.py

path('like/<int:blog_id>/', blogapp.views.likes, name="likes"),

 

detail.html

<a href="{% url 'likes' blog.id %}">
    {% if user in blog.like.all %}
    취소
    {% else %}
    좋아요
    {% endif %}
</a>

blog.like.all로 전체를 불러와 user가 포함되어 있다면(이미 좋아요를 누른 것이니) 취소를,

그 외의 상황이라면 좋아요 버튼을 보여줍니다.

 

 

자, 이렇게 좋아요 기능을 구현해보았는데요!

이렇게 간단하게 구현할 수 있으나,,,

현재는 좋아요 하나를 구현하기 위해서 전체 페이지를 렌더링하는 아주 비효율적인 

코드입니다.

 

그래서 다음  시간에 ajax에 대해 배워보며, 페이지의 일부분만 렌더링하며 만들 수 있도록 해보겠습니다!

댓글