ManyToMany를 활용한 팔로우 기능 구현

guava·2022년 1월 4일
0

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.

인스타그램에는 팔로우 기능이 있다.
이러한 팔로우는 유저와 유저같의 관계가 다대다로 구성이 된다. 특이한 점은 같은 User테이블 안에서 관계가 구성된다는 점이다.

장고의 ManyToMany 필드를 이용해서 이러한 팔로우 관계를 구현해본다.

모델


User

유저에 follower_set, following_set을 추가해준다.

  • follower_set: 유저가 팔로우 한 다른 유저 데이터(유저가 친구로 추가한 사람들)
  • follower_set: 유저를 팔로우 한 다른 유저 데이터(유저를 친구로 추가한 사람들)

유저간의 관계이므로 모델은 self로 지정해 주면 된다.

class User(AbstractUser):
    # ...

    follower_set = models.ManyToManyField('self', blank=True)
    following_set = models.ManyToManyField('self', blank=True)


팔로우, 언팔로우 뷰

  • 유저가 팔로우 한 다른 유저 데이터 및 유저를 팔로우 한 다른 유저 데이터를 수정한다.
  • request.META.get('HTTP_REFERER', 'root'): HTTP_REFERER 속성을 통해 요청한 페이지의 주소를 얻을 수 있다. 만약 URL로 직접 작성해서 요청하면 빈 값이다.
  • 뷰를 통해 데이터 수정 후 HttpResponse를 반환한다.
# accounts/views.py
@login_required
def user_follow(request, username):
    follow_user = get_object_or_404(User, username=username, is_active=True)

    # following_set : 유저가 팔로우 한 다른 유저(유저가 친구로 추가한 사람들)
    # follower_set: 유저를 팔로우 한 다른 유저 (유저를 친구로 추가한 사람들)
    request.user.following_set.add(follow_user)
    follow_user.follower_set.add(request.user)

    messages.success(request, f'{follow_user}님을 팔로우했습니다.')
    redirect_url = request.META.get('HTTP_REFERER', 'root')
    return redirect(redirect_url)

@login_required
def user_unfollow(request, username):
    unfollow_user = get_object_or_404(User, username=username, is_active=True)

    request.user.following_set.remove(unfollow_user)
    unfollow_user.follower_set.remove(request.user)

    messages.success(request, f'{unfollow_user}님을 언팔했습니다..')
    redirect_url = request.META.get('HTTP_REFERER', 'root')
    return redirect(redirect_url)

URL

요청 받을 주소를 정의한다. username을 뷰에 넘겨준다.

# accounts/urls.py
from django.urls import re_path
from . import views

urlpatterns = [
    # ...
    re_path(r'^(?P<username>[\w.@+-]+)/follow/$', views.user_follow, name='user_follow'),
    re_path(r'^(?P<username>[\w.@+-]+)/user_unfollow/$', views.user_unfollow, name='user_unfollow'),
]

템플릿


timeline_sidebar_user_follow.html

url reverse를 통해 user_follow, user_unfollow뷰에 GET요청을 한다.

별도의 자바스크립트 작업이 아닌, 서버에 의한 DB수정 작업을 거친 후 반환받은 URL로 이동한다.

<div class="d-flex mb-2">
  <div class="mr-3">
    <img src="{{ suggested_user.avatar_url }}" style="width: 32px; height: 32px;" class="rounded-circle">
  </div>
  <div>
    {{ suggested_user.username }}
  </div>
  <div class="ml-auto">
    <a href="{% url 'user_follow' suggested_user.username %}">Follow</a>
    <a href="{% url 'user_unfollow' suggested_user.username %}">Unfollow</a>
  </div>
</div>

0개의 댓글