1. Model Relationship (M:N)
ManyToMany
- M:N 관계 설정시 사용하는 모델 필드
- 예시) 좋아요
→ 한 명의 유저는 여러개의 게시글을 좋아할 수 있어요!
→ 하나의 게시글도 여러명의 유저에게 좋아요를 받을 수 있어요!
- 중계 테이블을 이용해서 관계를 표현
models.ManyToManyField(<classname>)
을 이용해서 설정
- M2M 관계가 설정되면 역참조시 사용 가능한
_set
이름의 RelatedManager를 생성
- related_name
으로 변경 가능
add()
, remove()
를 이용해서 관련 객체를 추가, 삭제
class Article(models.Model):
...
like_users = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name="like_articles"
)
...
- 중계 테이블을 내가 직접 정의하고, 그것을 지정하는 것도 가능
- through
를 사용해 중계 테이블 지정도 가능
class Article(models.Model):
...
like_users = models.ManyToManyField(
settings.AUTH_USER_MODEL, through="ArticleLike", related_name="like_articles"
)
...
class ArticleLike(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="like_articles"
)
article = models.ForeignKey(
Article, on_delete=models.CASCADE, related_name="like_users"
)
rating = models.IntegerField(default=1)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
follow
- 한 명의 유저는 여러명의 follower를 가질 수도 있고, 여러 명을 follow 할 수도 있음
→ M:N 관계
- User - User 관계를 맺는 모델을 자기 자신으로 명시
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
following = models.ManyToManyField(
"self", symmetrical=False, related_name="followers"
)
app_name = "users"
urlpatterns = [
...
path("<int:user_id>/follow/", views.follow, name="follow"),
]
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 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_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")