게시물 좋아요 구현 N:M

2star_·2024년 12월 16일
0

django

목록 보기
7/18

N:M

class ArticleLike(model.Model):
	article = models.ForeignKey(
    	Article, on_delete=models.CASCADE, related_name="likes"
        )
    user = models.ForeignKey(
    	settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="likes"
        )

article : 어떤 게시글에 좋아요를 눌렀는지
user : 누가 좋아요를 눌렀는지

article

  • ForeignKey: 이 필드는 다른 모델(Article)과 연결을 만든다. '좋아요'가 어떤 게시글을 가리키는지"를 나타낸다.
  • on_delete=models.CASCADE: 연결된 게시글이 삭제되면, 관련된 좋아요도 같이 삭제된다
  • related_name="likes": 반대쪽에서 게시글이 "자신과 연결된 좋아요들"을 쉽게 찾을 수 있도록 이름을 붙인다.
  • 예:

article_1= Article.objects.get(id=1)
article_1.likes.all() → 1번 게시물에 달린 모든 좋아요를 가져옴

user

  • settings.AUTH_USER_MODEL: Django의 사용자 모델과 연결. 즉, "좋아요를 누른 사용자가 누구인지"를 나타낸다.
  • related_name="likes": 반대로, 사용자가 자신이 누른 좋아요들을 쉽게 찾을 수 있도록 이름을 붙임
  • 예:
    admin_user = User.objects.get(id=1)
    admin_user.likes.all() → 사용자가 누른 모든 좋아요를 가져옴


ManyToManyField

위와 같이 중계 테이블을 하나 정의해서 articleuser를 연결 해 줄수 있지만, 장고에서는 간편하게 models.ManyToManyField을 이용하면, 다대다 관계를 중계테이블 따로 정의하지 않아도 정의할 수 있다.

예시 코드

class Article(models.Model):
.
.
.
    
    like_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL, related_name="like_articles"
    )
    

하지만 더 많은 정보, 예를들어 좋아요의 정도 (1~5점)을 표현하고 싶을땐 중계테이블 정의해서 활용해야함
through를 활용한 중계테이블 지정

urls, views

urls


urlpatterns = [
.
.
.
	path('<int:pk>/like/', views.like, name="like"),

views

  1. 로그인 여부 파악
  2. article 조회
  3. 이미 article에 대한 좋아요가 있는 경우 취소(remove)
  4. article에 대한 좋아요를 하지 않았다면 등록(add)
  5. 게시물 리스트로 redirect 시키기
@require_POST
def like(request, pk):
    if request.user.is_authenticated:
        article = get_object_or_404(Article, pk=pk)
        if article.like_users.filter(pk=request.user.pk).exists():
            article.like_users.remove(request.user) # 좋아요 취소
        else:
            article.like_users.add(request.user) # 좋아요
        return redirect("articles")
    return redirect("login")

htmls

{% extends 'base.html' %}

{% block content %}
<h2> Articles</h2>
<a href="{% url 'create' %}">
    <button>새로운 글 작성</button>
    </a>
{% for article in articles %}
    <a href="{% url 'article_detail' article.pk %}">
    <p> [{{ article.pk }}]{{ article.title }} </p>
    </a>
    <form action="{% url 'like' article.pk %}" method="POST">
        {% csrf_token %}
        {% if request.user in article.like_users.all %}
            <input type="submit" value="안좋아요">
        {% else %}
            <input type="submit" value="좋아요">
        {% endif %}
    </form>
{% endfor %}
{% endblock content %}

{% if request.user in article.like_users.all %}

여기서 article.like_users.all()이렇게 괄호를 쓰지 않는 이유는 Django 템플릿의 특수성때문이다. 괄호를 쓰지 않아도 템플릿 엔진이 자동으로 all()을 호출한다. 이점이 python 코드와 좀 다른 부분이다.!


profile
안녕하세요.

0개의 댓글

관련 채용 정보