2022. 2. 22. 22:44ㆍ강의 정리/Django 기초
장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!
Django 포스팅 좋아요 / 취소 구현하기
#insta/models.py
class Post(BaseModel):
author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="my_post_set", on_delete=models.CASCADE)
# 중략
like_user_set = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="like_post_set", blank=True)
_필드의 related_name 옵션을 설정해주면, 쿼리셋시에 related_name을 이용하여 모델 객체를 불러올 수 있습니다.
ex)
기존 -> Post.objects.filter(author=user)
related_name -> user.my_post_set.all()
_related_name 이란
참조되는 테이블이 참조하는 테이블의 데이터를 가져오고 싶을 때 사용하는 이름을 정의하는 것입니다,
_ManyToManyField 란??
https://velog.io/@jiffydev/Django-9.-ManyToManyField-1
_user.my_post_set은 유저가 작성한 포스팅에 접근하게 되고, user.like_post_set은 유저가 좋아요를 누른 포스팅에 접근하게 됩니다.
#insta/urls.py
urlpatterns = [
path('post/<int:pk>/like', views.post_like, name='post_like'),
path('post/<int:pk>/unlike', views.post_unlike, name='post_unlike'),
]
_ post_detail에 맞게 즉 포스팅 디테일뷰가 보여지는 url과 똑같이 매핑합니다.
#insta/views.py
# 포스팅 좋아요
@login_required
def post_like(request, pk):
post = get_object_or_404(Post, pk=pk)
post.user_like_set.add(request.user)
messages.success(request, f"{post}를 좋아합니다.")
redirect_url = request.META.get("HTTP_REFERER", "root") # HTTP_REFERER은 request 요청을 한 웹페이지의 주소를 보여준다.
# 만약 HTTP_REFERER가 없으면 root 주소를 가져온다.
return redirect(redirect_url)
# 포스팅 싫어요
@login_required
def post_unlike(request, pk):
post = get_object_or_404(Post, pk=pk)
post.user_like_set.remove(request.user)
messages.success(request, f"{post}를 좋아요를 취소합니다.")
redirect_url = request.META.get("HTTP_REFERER", "root") # HTTP_REFERER은 request 요청을 한 웹페이지의 주소를 보여준다.
# 만약 HTTP_REFERER가 없으면 root 주소를 가져온다.
return redirect(redirect_url)
_ request.META.get()이란??
request.META는 사용자의 IP 주소와 사용자 Agent(일반적으로 웹 브라우저의 이름과 버전)를 포함해 지정된 요청에 대해 사용할 수 있는 모든 HTTP 헤더가 들어있는 파이썬 딕셔너리 입니다.
출처 : https://yonghyunlee.gitlab.io/python/django-master-6/
템플릿단
#insta/templates/insta/_post_card.html
{% load bootstrap4 %}
{% load insta_tags %}
<div class="card">
<div class="card-header">
<img src= "{{ user.profile_url }}" style="width: 24px; height: 24px;"/>
<a href="{% url "insta:user_page" post.author.username %}" style="text-decoration:none">
{{ post.author }}
</a>
</div>
<div class="card-body">
{% if post.photo.url %}
<img src="{{ post.photo.url }}" style="width: 100%;"/>
{% endif %}
{% for tag in post.tag_set.all %}
<span class="badge badge-primary" style="color: #fff;
background-color: #007bff;">
#{{ tag.name }}
</span>
{% endfor %}
</div>
<div class="card-footer">
{% if post|is_like_user:user %}
<a href="{% url 'insta:post_unlike' post.pk %}" style="text-decoration:none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FF0000" class="bi bi-heart-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z"/>
</svg>
</a>
{% else %}
<a href="{% url 'insta:post_like' post.pk %}" style="text-decoration:none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FF0000" class="bi bi-heart" viewBox="0 0 16 16">
<path d="m8 2.748-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z"/>
</svg>
</a>
{% endif %}
</div>
</div>
{{ post|is_like_user:user }}
_ Pipe(='|') 앞의 인자"post"는 tags.py 함수의 첫번째 인자로 넘어가고, "user"은 두번째 인자로 넘어갑니다.
아래 코드는 위 이해를 돕기위한 tags.py의 함수입니다.
@register.filter
def is_like_user(post, user):
# 해당 글의 is_like_user를 반환 하여줍니다.
return post.is_like_user(user)
_위 tags.py 함수는 모델단의 함수를 호출시켜줍니다.
# 만약 유저가 포스팅을 좋아한다면(=like_user_set에 유저 pk가 있다면) True를 반환
def is_like_user(self, user):
return self.like_user_set.filter(pk=user.pk).exists()
템플릿에서 -> tags.py 함수 호출 -> tags.py에서 model단 함수 호출
_ 아이콘을 지원해주는 사이트들
https://icons.getbootstrap.kr/
_장고 템플릿 단에서 함수를 호출하고, 인자를 넘기고 싶다면 Django custom templates filter를
적용해야합니다.
https://docs.djangoproject.com/ko/4.0/howto/custom-template-tags/
0. 해당 앱에 templatestags 라는 폴더를 만들어줍니다.
1. templatestags 폴더 안에 '__init__.py'와 'app이름_tags.py'를 만들어줍니다.
#insta/templatetags/insta_tags.py
from django import template
register = template.Library()
@register.filter
def is_like_user(post, user):
# 해당 글의 is_like_user를 반환 하여줍니다.
return post.is_like_user(user)
'강의 정리 > Django 기초' 카테고리의 다른 글
Django로 인스타그램 클론 코딩시 필요한 Skill (0) | 2022.03.12 |
---|---|
Django 인스타그램 follow 기능 구현 (0) | 2022.02.17 |
Django 인스타그램 Timeline sidebar 구현하기 (0) | 2022.02.17 |
Django 포스팅 쓰기 구현하기 (0) | 2022.02.14 |
Django 암호 수정 구현하기 (0) | 2022.02.08 |