∟ Framework/⊢ Django

Django - Model Relationship (M:N)

최 수빈 2025. 2. 24. 05:58

 

ManyToMany Relationship in Django

 

 

좋아요 (Like) 기능 구현

User가 특정 Article에 좋아요(Like)를 누르는 기능

→ User가 어떤 Article에 좋아요를 눌렀는지 저장

 

articles/models.py

1차 구현 (1:N 관계)

class Article(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="articles"
    )
    like_user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="like_articles",
        null=True
    )
  • 동일 Article에 여러 명이 '좋아요' 누를 수 없음 → 해결 필요

 

2차 구현 (별도 중계 테이블 활용)

class ArticleLike(models.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"
    )
  • ArticleLike 테이블을 만들어 M:N 관계를 직접 처리 가능

aricles/model.py - ArticleLike 중계테이블 구현

 

 

ManyToManyField 활용한 최종 구현

class Article(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="articles"
    )
    like_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL, related_name="like_articles"
    )
  • Django의 ManyToManyField를 활용, 중계 테이블을 자동 생성하여 간편하게 구현 가능
  • like_users.add(user)like_users.remove(user)로 좋아요 추가/취소 가능

articles/models.py - ManyToManyField 활용한 최종 구현

 

ManyToMany Field

 

Model field reference | Django documentation

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

 

 

 

좋아요 기능 관련 URL 및 뷰 구현

 

URL 설정 (articles/urls.py)

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

articles/urls.py

View 함수 구현 (articles/views.py)

@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)
    else:
        return redirect("accounts:login")
    return redirect("articles:articles")

articles/views.py - like함수 구현

 

좋아요 버튼 추가 (articles.html)

{% for article in articles %}
    <form action="{% url 'articles:like' article.pk %}" method="POST">
        {% csrf_token %}
        {% if user in article.like_users.all %}
            <input type="submit" value="좋아요 취소">
        {% else %}
            <input type="submit" value="좋아요">
        {% endif %}
    </form>
{% endfor %}

 

팔로우 (Follow) 기능 구현

 

한 명의 User가 여러 명의 User를 팔로우할 수 있음

한 명의 User는 여러 명의 팔로워를 가질 수 있음

User - User 간의 M:N 관계

 

모델 구현 (ManyToManyField 활용)

accounts/models.py

 

from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    following = models.ManyToManyField(
        "self", symmetrical=False, related_name="followers"
    )
  • symmetrical=False를 설정하여 대칭적이지 않은 관계(한쪽만 팔로우 가능) 구현
  • Django는 M2M 관계를 위한 자동 중계 테이블 생성

 

팔로우 기능 관련 URL 및 뷰 구현

 

URL 설정 (users/urls.py)

users/urls.py

urlpatterns = [
    path("<int:user_id>/follow/", views.follow, name="follow"),
]

 

View 함수 구현 (users/views.py)

@require_POST
def follow(request, user_pk):
    if request.user.is_authenticated:
        member = get_object_or_404(get_user_model(), pk=user_pk)
        if request.user != member:
            if request.user in member.followers.all():
                member.followers.remove(request.user)
            else:
                member.followers.add(request.user)
        return redirect("users:profile", member.username)
    return redirect("accounts:login")

users.views.py

 

팔로우 버튼 추가 (profile.html)

{% block content %}
    <h1>{{ member.username }}의 프로필 페이지</h1>
    <div>
        <h2>username: {{ member.username }}</h2>
        <p>
            팔로워: {{ member.followers.count }}명
            팔로잉: {{ member.following.count }}명
        </p>
    </div>
    <div>
        <form action="{% url 'users:follow' member.pk %}" method="POST">
            {% csrf_token %}
            {% if user in member.followers.all %}
                <button type="submit">언팔로우</button>
            {% else %}
                <button type="submit">팔로우</button>
            {% endif %}
        </form>
    </div>
    <a href="/index/">홈으로 돌아가기</a>
{% endblock content %}

users/templates/users/profile.html

 

최종 articles/templates/articles/article.html

articles/templates/articles/articles.html
/articles/

 

 


  • 좋아요 기능은 ManyToManyField를 사용하면 간편하게 구현 가능
  • 팔로우 기능은 ManyToManyField('self', symmetrical=False)로 구현 가능
  • Django ORM을 활용하면 M:N 관계의 데이터 처리 및 조회가 매우 직관적이고 간단해짐
  • add(), remove() 메서드를 활용하여 관계를 쉽게 조작 가능

'∟ Framework > ⊢ Django' 카테고리의 다른 글

Django - Bootstrap, FontAwesome 활용  (1) 2025.02.27
Django - Custom User Model  (0) 2025.02.24
Django - 1:N 관계 (Many-to-One Relationships)  (1) 2025.02.20
Django - Admin Site 활용  (1) 2025.02.13
Django - Static & Media  (2) 2025.02.08