728x90
Pystagram Project (4)
1. 글 상세 페이지
- Post에 대한 상세 페이지 구현
- Template의 중복된 내용을 제거하는 리팩토링 실행
1.1 글 상세 페이지
1.1.1 기본구조 구현
- View: posts/views.py → post_detail
- URL: /posts/int:post_id/
- Template: templates/posts/post_detail.html
- posts/views.py
def post_detail(request, post_id):
post = Post.objects.get(id=post_id)
context = { "post": post }
return render(request, "posts/post_detail.html", context)
|
- posts/urls.py
from posts.views import ..., post_detail
app_name = "posts"
urlpatterns = [
...
path("<int:post_id>/", post_detail, name="post_detail"),
]
|
- templates/posts/post_detail.html
{% extends 'base.html' %}
{% block content %}
<div id="post_detail">
<h1>Post Detail</h1>
</div>
{% endblock %}
|
1.1.2 Template 내용 구현
- templates/posts/feeds.html
{% extends 'base.html' %}
{% block content %}
<nav>...</nav>
<div id="feeds" class="post-container">
{% for post in posts %}
<article id="post-{{ post.id }}" class="post">
...
</article>
{% endfor %}
</div>
...
{% endblock %}
|
- templates/posts/post_detail.html
- 피드페이지에서는 for 반복문 안의 < article> 요소가 각각 하나의 Post를 나타냄
- Post 상세화면에서는 Post Queryset 대신 단일 Post 객체가 전달되며 나머지 모습은 피드페이지와 동일함
{% extends 'base.html' %}
{% block content %}
<div id="feeds" class="post-container">
<article id="post-{{ post.id }}" class="post">
...
</article>
</div>
{% endblock %}
|
1.1.3 PostForm 전달
- posts/views.py
def post_detail(request, post_id):
post = Post.objects.get(id=post_id)
comment_form = CommentForm()
context = {
"post": post,
"comment_form": comment_form,
}
return render(request, "posts/post_detail.html", context)
|
1.1.4 {% include %} 태그로 Template 재사용
- templates/posts/post.html
- < article> 태그를 post.html로 재사용
<article id="post-{{ post.id }}" class="post">
...
</article>
|
- templates/posts/feed.html
{% extends 'base.html' %}
{% block content %}
<nav>...</nav>
<div id="feeds" class="post-container">
{% for post in posts %}
{% include 'posts/post.html' %}
{% endfor %}
</div>
...
{% endblock %}
|
- templates/posts/post_detail.html
{% extends 'base.html' %}
{% block content %}
<nav>...</nav>
<div id="feeds" class="post-container">
{% include 'posts/post.html' %}
</div>
...
{% endblock %}
|
- templates/nav.html
- < nav> 태그의 내용을 별도의 nav.html로 이동
<nav>
<h1>
<a href="{% url 'posts:feeds' %}">Pystagram</a>
</h1>
<a href="{% url 'posts:post_add' %}">Add post</a>
<a href="{% url 'users:logout' %}">Logout</a>
</nav>
|
- templates/posts/feeds.html, templates/posts/post_detail.html 공통
{% extends 'base.html' %}
{% block content %}
{% include 'nav.html' %}
<div id="feeds" class="post-container">
{% include 'posts/post.html' %}
</div>
...
{% endblock %}
|
1.1.5 해시태그 검색결과에 링크 추가
- templates/posts/tags.html
<div class="post-grid">
<a href="{% url 'posts:post_detail' post_id=post.id %}">
<img src="{{ post.postimage_set.first.photo.url }}" alt="">
</a>
</div>
|
1.2 글 작성 후 이동할 위치
1.2.1 Post 상세 화면에서 댓글 작성 시 상세화면으로 이동
- posts/views.py
- 기존의 댓글 작성 후 redirect
def comment_add(request):
...
if form.is_valid():
...
url_next = reverse("posts:feeds") + f"#post-{comment.post.id}"
return HttpResponseRedirect(url_next)
|
- templates/posts/post_detail.html
- 댓글은 피드 페이지와 글 상세 페이지 양쪽에서 작성할 수 있음
- 댓글 작성 완료 후 사용자를 이동시킬 페이지를 각각의 경우에 따라 다르게 지정할 필요가 있음
...
<div id="feeds" class="post-container">
{% url 'posts:post_detail' post.id as action_redirect_to %}
{% include 'posts/post.html' with action_redirect_url=action_redirect_to %}
</div>
...
|
- templates/posts/post.html
...
<div class="post-comment-create">
<form method="POST" action="{% url 'posts:comment_add' %}?next={{ action_redirect_url }}">
{% csrf_token %}
<input type="hidden" name="post" value="{{ post.id }}">
{{ comment_form.content }}
<button type="submit">게시</button>
</form>
</div>
...
|
- posts/views.py
def comment_add(request):
...
if form.is_valid():
...
comment.save()
# URL로 "next"값을 전달받았다면 댓글 작성 완료 후 전달받은 값으로 이동한다
if request.GET.get("next"):
url_next = request.GET.get("next")
# "next"값을 전달받지 않았다면 피드페이지의 글 위치로 이동한다
else:
url_next = reverse("posts:feeds") + f"#post-{comment.post.id}"
return HttpResponseRedirect(url_next)
|
- templates/posts/feeds.html
...
<div id="feeds" class="post-container">
{% for post in posts %}
{% with post.id|stringformat:"s" as post_id %}
{% url 'posts:feeds' as action_redirect_to %}
{% include 'posts/post.html' with action_redirect_url=action_redirect_to|add:'#post-'|add:post_id %}
{% endwith %}
{% endfor %}
</div>
...
|
1.2.2 Custom Template Filter
- posts/templatetags/custom_tags.py
from django import template
register = template.Library()
@register.filter
def concat(value, arg):
return f"{value}{arg}"
|
- templates/posts/feeds.html
{% extends 'base.html' %}
{% load custom_tags %}
{% block content %}
{% include 'nav.html' %}
<div id="feeds" class="post-container">
{% for post in posts %}
{% url 'posts:feeds' as action_redirect_to %}
{% include 'posts/post.html' with action_redirect_url=action_redirect_to|concat:'#post-'|concat:post_id %}
{% endfor %}
</div>
...
{% endblock %}
|
- templates/posts/post_detail.htlm
- 해쉬태그 타고 들어갔을때 이미지 안나오는거 해결
{% extends 'base.html' %}
{% block content %}
{% include 'nav.html' %}
<div id="feeds" class="post-container">
{% url 'posts:post_detail' post.id as action_redirect_to %}
{% include 'posts/post.html' with action_redirect_url=action_redirect_to %}
</div>
<script>
const elms = document.getElementsByClassName('splide')
for (let i = 0; i < elms.length; i++){
new Splide(elms[i]).mount();
}
</script>
{% endblock %}
|
728x90
'PYTHON-BACK' 카테고리의 다른 글
#파이썬 32일차_온라인 상점 구축 프로젝트1 (0) | 2024.08.23 |
---|---|
#파이썬 34일차_이커머스 클론코딩5_(2) (0) | 2024.08.22 |
#파이썬 34일차_이커머스 클론코딩4_(2) (0) | 2024.08.21 |
#파이썬 34일차_이커머스 클론코딩4_(1) (0) | 2024.08.21 |
#파이썬 33일차_이커머스 클론코딩3 (0) | 2024.08.20 |