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
: 누가 좋아요를 눌렀는지
ForeignKey
: 이 필드는 다른 모델(Article)과 연결을 만든다. '좋아요'가 어떤 게시글을 가리키는지"를 나타낸다.on_delete=models.CASCADE
: 연결된 게시글이 삭제되면, 관련된 좋아요도 같이 삭제된다related_name="likes"
: 반대쪽에서 게시글이 "자신과 연결된 좋아요들"을 쉽게 찾을 수 있도록 이름을 붙인다.article_1= Article.objects.get(id=1)
article_1.likes.all()
→ 1번 게시물에 달린 모든 좋아요를 가져옴
settings.AUTH_USER_MODEL
: Django의 사용자 모델과 연결. 즉, "좋아요를 누른 사용자가 누구인지"를 나타낸다.related_name="likes"
: 반대로, 사용자가 자신이 누른 좋아요들을 쉽게 찾을 수 있도록 이름을 붙임admin_user = User.objects.get(id=1)
admin_user.likes.all()
→ 사용자가 누른 모든 좋아요를 가져옴위와 같이 중계 테이블을 하나 정의해서 article
과 user
를 연결 해 줄수 있지만, 장고에서는 간편하게 models.ManyToManyField
을 이용하면, 다대다 관계를 중계테이블 따로 정의하지 않아도 정의할 수 있다.
예시 코드
class Article(models.Model):
.
.
.
like_users = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name="like_articles"
)
하지만 더 많은 정보, 예를들어 좋아요의 정도 (1~5점)을 표현하고 싶을땐 중계테이블 정의해서 활용해야함
through
를 활용한 중계테이블 지정
urlpatterns = [
.
.
.
path('<int:pk>/like/', views.like, name="like"),
@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")
{% 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 코드와 좀 다른 부분이다.!