Django M:N 관계 - User끼리의 follow 구현하기
models.py
class User(AbstractUser):
followings = models.ManyToManyField('self', symmetrical=False, related_name='followers')
user 모델에 followings 필드를 추가한다.
user 자신과의 관계이기 때문에 'self'라고 작성한다.
symmetrical=True면 대칭으로, 자동으로 팔로잉-팔로워가 같게 반영되는 것이므로 팔로잉,팔로워를 따로 관리하기 위해서 False로 한다.
follow하는 것은 이 필드에 해당되고, 역참조는 followers가 된다.
기본 buit-in 유저모델을 사용했다면 user에 필드를 추가할 수 없다.
이런 것 때문에 built-in user를 상속받아 새로 만든 것이다.
ManyToManyField로 자동 생성된 중개테이블은 다음과 같다.

같은 모델으로 관계를 만든 것이기 때문에 from, to 필드로 생성되었다.
accounts - urls.py
path('<int:user_pk>/follow/', views.follow, name='follow'),
follow url 추가한다.
accounts - views.py
@require_POST
def follow(request, user_pk):
User = get_user_model()
person = User.objects.get(pk=user_pk)
if request.user in person.followers.all():
person.followers.remove(request.user)
else:
person.followers.add(request.user)
@require_POST
def follow(request, user_pk):
if request.user.is_authenticated:
User = get_user_model()
me = request.user
you = User.objects.get(pk=user_pk)
if me != you:
if me in you.followers.all():
you.followers.remove(me)
else:
you.followers.add(me)
return redirect('accounts:profile', you.username)
return redirect('accounts:login')
me, you로 보기쉽게 정의해주었다.
자신을 팔로우하면 안되기 때문에 me!=you 조건을 추가한다.
if you.followers.filter(pk=me.pk).exists():
exists()으로 하려면 위와 같다.
accounts - template - profile.html
<div>
팔로워 : {{ person.followers.all|length }} / 팔로잉 : {{ person.followings.all|length }}
</div>
{% if request.user != person %}
<div>
<form action="{% url 'accounts:follow' person.pk %}" method="POST">
{% csrf_token %}
{% if request.user in person.followers.all %}
<input type="submit" value="언팔로우">
{% else %}
<input type="submit" value="팔로우">
{% endif %}
</form>
<div>
{% endif %}
프로필에 팔로우 부분을 추가한다.
내 프로필이 아닌경우 팔로우, 언팔로우 버튼이 뜨도록 했다.
팔로워 목록에 내가 있으면 언팔로우 / 없으면 팔로우 버튼이다.
length를 이용해서 팔로워, 팔로잉 수를 출력할 수도 있다.
여기서는 in 으로 followers를 확인하는 문법을 filter로 사용할 수 없다.
filter()으로 괄호로 메서드를 호출해야하는데 dtl에서는 ()으로 메서드를 호출하지 않기 때문이다.
{% if you.followers.filter(pk=me.pk).exists(): %} <<< - 안된다!

2번이 1번을 follow하고 있는 것을 확인한다.
'Back-end > Django' 카테고리의 다른 글
REST API, 1:N, M:N - movie, actor, review (0) | 2022.10.21 |
---|---|
Fixtures - dumpdata, loaddata (0) | 2022.10.12 |
Django M:N 관계 - 좋아요 버튼 / 프로필 페이지 (0) | 2022.10.12 |
Aggregation (Grouping data) (0) | 2022.10.12 |
Django M:N 관계 - ManyToManyField (0) | 2022.10.12 |