2022. 2. 23. 13:05ㆍ강의 정리/Django
장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!
Django 댓글 구현하기
#insta/models.py
class BaseModel(models.Model):
class Meta:
# 아래 코드를 통해 실제 DB에 적용되지 않고, 추상 클래스로 만들어진다.
abstract = True
class Comment(BaseModel):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
message = models.TextField()
class Meta:
ordering = ['-id']
_ 항상 모델단에 ordering을 통해 정렬을 하는것을 추천합니다.
_ Django에서는 정수나 날짜등을 사람이 보기 보다 편하게 해주는 템플릿 필터가 존재합니다.
ex) 예를 들어 숫자에 컴마를 찍어준다거나, 날짜를 today, yesterday등으로 바꿔줍니다.
https://docs.djangoproject.com/en/4.0/ref/contrib/humanize/
_반드시 humanize를 INSTALLED_APPS에 먼저 추가 시켜주어야 합니다.
INSTALLED_APPS = [
# Django Apps
'django.contrib.humanize', # 추가
]
#insta/templates/insta/_post_card.html
{% load bootstrap4 humanize 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 %}
<div>
{% 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 class="comment-list mt-3 mb-3">
{% for comment in post.comment_set.all %}
<div class="comment">
<strong>{{ comment.author }}</strong>
{{ comment.message }}
<small class="text-muted">{{ comment.created_at|naturaltime }}</small>
</div>
{% endfor %}
</div>
<div>
{% for tag in post.tag_set.all %}
<span class="badge badge-primary" style="color: #fff;
background-color: #007bff;">
#{{ tag.name }}
</span>
{% endfor %}
</div>
<div>
<a href="{{ post.get_absolute_url }}" style="text-decoration:none" class="text-muted">
<small>
{{ post.created_at|naturaltime }}
</small>
</a>
</div>
</div>
<div class="card-footer">
<a href="{% url 'insta:comment_new' post.pk %}">
댓글 쓰기
</a>
</div>
</div>
_반드시 템플릿 최상단에 humanize를 load 해주어야 오류가 안납니다!
#insta/forms.py
from django import forms
from .models import Post, Comment
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
'photo', 'caption', 'location'
]
# 장고에서는 widgets 를 통해 특정 필드 위젯을 변경할 수 있다.
widgets = {
"caption" : forms.Textarea,
}
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ["message"]
#insta/urls.py
urlpatterns = [
# 아래 path에서는 comment가 주인공이기에 post_pk로 작성
path('post/<int:post_pk>/comment/new/', views.comment_new, name='comment_new'),
]
#insta/views.py
# 댓글 쓰기
@login_required
def comment_new(request, post_pk):
post = get_object_or_404(Post, pk=post_pk)
if request.method == 'POST':
form = CommentForm(request.POST, request.FILES)
if form.is_valid():
# 내부적으로 comment가 save되는 것을 막음
# 그 이유는 댓글 폼은 message 필드만 받기 때문에, 나머지 필드에서 오류가 생기기 때문이다.
# 그러기에 나머지 필드를 채워준 상태에서 form을 저장 시켜야한다.
comment = form.save(commit=False)
comment.post = post
comment.author = request.user
comment.save()
return redirect(comment.post)
else:
form = CommentForm()
return render(request, "insta/comment_form.html", {
"form" : form,
})
_ commit=False를 쓰는 이유는?
예를 들어서 필드가 4개가 있는 모델을 모델 폼으로 작성을 받을 때
나는 그 중 1개의 필드만 폼으로 작성하고 싶다!!
이 경우에 view 함수에서 유효성 검사 이후 form.save()를 먼저 하면 나머지 필드들은 값을 받지
못했으므로 오류가 발생합니다!
그러기에 우리는 장고에게 잠시만 저장을 미뤄줘~~! 라는 의미로 commit=False를 적어준 다음
나머지 필드들의 값을 지정해주는겁니다!
#insta/templates/insta/comment_form.html
{% extends "insta/layout.html" %}
{% load bootstrap4 %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-6 offset-sm-3">
{% include "_form.html" with form_title="새 댓글 쓰기" submit_label="새 댓글 쓰기" %}
</div>
</div>
</div>
{% endblock %}
'강의 정리 > Django' 카테고리의 다른 글
동백 // Django admin을 통한 데이터 관리 (기초) (0) | 2021.12.27 |
---|