📗 Django
ManyToMany Relationship
좋아요와 팔로우 기능은 어떻게 만드는 걸까?
- 좋아요 기능이 뭘까?
- User가 Article에 좋아요(Like)를 누르는 것
- 저장해야 할 데이터는 뭘까?
- User가 어떤 Article에 좋아요를 눌렀는지 저장
ManyToMany 🔗 공식 문서
- 다대다(M:N) 관계 설정 시 사용하는 모델 필드이다.
- 예시) 좋아요
- 하나의 게시글도 여러 명의 유저에게 좋아요를 받을 수 있다
- 한 명의 유저는 여러 개의 게시글을 좋아할 수 있다
- 예시) 좋아요
- 중계 테이블을 이용해서 관계를 표현
- models.ManyToManyField(<classname>)을 이용해서 설정
- M2M 관계가 설정되면 역참조시 사용가능한 _set이름의 RelatedManager를 생성합니다.
- related_name으로 변경 가능
- add(), remove()를 이용해서 관련 객체를 추가, 삭제할 수 있다.
좋아요 구현하기
- articles/models
- migration 실행
더보기




articles/models.py

Like_users = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name="Like_articles")
migration

python manage.py makemigrations
python manage.py migrate

새로 생긴 0003. article_like_users.py

중계 테이블도 만들어졌다
ORM 연습하기
▪️ article과 user 불러오기
더보기



# aritcle 가져오기
Article.objects.all()
# Users 불러오기
User.objects.all()
# article_1은 id 1로 지정하기
article_1 = Article.objects.get(id=1)

# admin_user는 id 1로 불러와지게 설정하기
admin_user = User.objects.get(id=1)
# MinKyung_user는 id 2로 불러와지게 설정하기
MinKyung_user = User.objects.get(id=2)
▪️ 좋아요 추가, 조회하기
더보기




article_1.Like_users.add(admin_user)
article_1.Like_users.add(MinKyung_user)
article_1.Like_users.all()
- admin_user → article_1 : 좋아요
- MinKyung_user → article_1 : 좋아요
- article_1을 좋아하는 모든 user 목록
# 좋아요 취소하기
article_1.Like_users.remove(MinKyung_user)
# user가 article에 좋아요 남겼다고 작성할 수도 있다.
MinKyung.Like_articles.add(article_1)

왜 안 되나 했더니,

Like_users로 해둬서 안 됐던 거였다,,
like_users가 아니라 Like_users였던 것,,
▪️ article_article_like_users 중계테이블
더보기



- article_1번 글에 user_id가 1과 2인 사람이 눌렀음을 보여줌
- Django에서 자동으로 중계테이블을 만들어주었다.
좋아요에 ‘정도’를 표현하고 싶다면?
- 중계테이블을 내가 직접 정의해줄 수도 있다

- articles/urls
더보기


path('<int:pk>/like/', views.like, name="like"),
- articles/views
더보기


# 좋아요
@require_POST
def like(request, pk):
if request.user.is_authenticated:
article = get_object_or_404(Article, pk=pk)
# 만약 article에 좋아요가 user.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:articles")
return redirect("accounts:login")
- articles.html
더보기






<form action="{% url "articles:like" article.pk %}" method="POST">
{% csrf_token %}
{% if request.user in article.Like_users.all %}
<input type="submit" value="Cancle Like">
{% else %}
<input type="submit" value="Like">
{% endif %}
</form>
<article.pk에 like 주소로 가게끔>
<form action="{% url "articles:like" article.pk %}" method="POST">
{% csrf_token %}
<만약에, article.Like_users.all에 user가 있다면, 좋아요 취소>
{% if request.user in article.Like_users.all %}
<input type="submit" value="Cancle Like">
<article.Like_users.all에 user가 없다면, 좋아요>
{% else %}
<input type="submit" value="Like">




되넹!
팔로우
🤔 팔로우는 어떻게 구현할 수 있을까?
- 한 명의 유저는 여러 명의 유저를 팔로우할 수 있어요!
- 한 명의 유저는 여러 명의 팔로워를 가질 수 있어요!
⇒ M:N 관계
누구랑 m2m 관계를 맺어야 할까?
⇒ USER - USER
symmetrical
- M2M Field가 동일한 모델(self)과 관계를 맺는 경우에 사용
- symmetrical=True인 경우 한 방향에서 관계를 맺으면 반대 관계도 설정된다. (대칭)
- 기본값은 True
팔로우 구현하기
- accounts/models.py
- migration 하기
더보기





class User(AbstractUser):
followings = models.ManyToManyField(
"self", related_name="followers", symmetrical=False)
migrate 하기

python manage.py makemigrations
python manage.py migrate


잘 생성됐다
- users/urls.py
더보기


path("<int:user_id>/follow/", views.follow, name="follow"),
- users/views.py
더보기


from django.shortcuts import render, redirect
from django.views.decorators.http import require_POST
from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model
def users(request):
return render(request, "users/users.html")
def profile(request, username):
member = get_object_or_404(get_user_model(), username=username)
context = {"member": member,}
return render(request, "users/profile.html", context)
@require_POST
def follow(request, user_id):
if request.user.is_authenticated:
member = get_object_or_404(get_user_model(), pk=user_id)
if member != request.user:
if member.followers.filter(pk=request.user.pk).exists():
member.followers.remove(request.user)
else:
member.followers.add(request.user)
return redirect("users:profile", member.username)
return redirect("accounts:login")
- profile.html
더보기




{% extends 'base.html' %}
{% block content %}
<h1>Profile of {{ member.username }}</h1>
<div>
<h2>username : {{ member.username }}</h2>
{% if request.user != member %}
<form action="{% url "users:follow" member.pk %}" method="POST">
{% csrf_token %}
{% if request.user in member.followers.all %}
<input type="submit" value="Unfollow">
{% else %}
<input type="submit" value="Follow">
{% endif %}
</form>
{% endif %}
</div>
<a href="/index/">Back to the index</a>
{% endblock content %}


admin으로 들어가서 MinKyung 프로필에 들어가니까 작동 잘 된다.
'🔥 공부 > 📘 Django 공부' 카테고리의 다른 글
[Django] 페이지네이션(pagination) (0) | 2025.03.26 |
---|---|
[Django] Django 기초 마무리 (0) | 2025.01.19 |
[Django] Custom UserModel 활용하기 (0) | 2025.01.18 |
[Django] Model Relationship (1:N), 댓글 (0) | 2025.01.18 |
[Django] Django Admin (0) | 2025.01.17 |