media 절대경로 수정(settings.py)
DB에 파일업로드 받을 필드 추가
📢post 게시물 예외처리
post list 존재 여부에 따른 출력하여 예외처리 하자.
- blog/templates/blog/post_list.html
<!-- Page content --> <section class="container"> ... <div class="row"> <!-- Blog entries--> <div class="col-lg-8"> {% if post_list.exists %} {% for p in post_list %} <!-- Featured blog post--> <div class="card mb-4"> ... ... ... </div> </section> {% else %} <h3>아직 게시물이 없습니다.</p> {% endif %}
class PostList(ListView):
model = Post
# template_name = 'blog/post_list.html'
paginate_by = 2 # pagination 기능 활성화, page 당 2
ordering = '-pk'
https://www.notion.so/4-9-paginations-b842ba4b05184a9687779159a1141e08
ForeignKey로 연결되어 있던 카테고리가 삭제된 경우 포스트까지 삭제되지 않고 category필드만 null이 되도록 on_delete=models.SET_NULL
로 설정
get_context_data
메서드를 내장하고있다.get_context_data
를 2가지 정보를 담기로 정의했다.Category.objects.all()
과 Post.objects.filter(category=None)
으로카테고리에 따로 모아놓은 텍스트 링크를 클릭 시,
get_absolute_url()
class Category(models.Model):
...
...
def get_absolute_url(self):
return f'/blog/category/{self.slug}/'
category_page()
함수의 매개변수인 slug의 인자로 넘겨주도록 했다.urlpatterns = [
path('category/<str:slug>/', views.category_page),
...
]
1) FBV 방식, request 이외에 slug까지 설정했다. category_page() 함수의 인자로 받은 slug와 동일한 slug를 갖는 카테고리를 불러오는 쿼리셋을 만들어 category변수에 저장한다. 추가로, 미분류인지 아닌지에 대한 예외처리한 상태이다.
2) 템플릿
3) PostList 클래스에서 context로 정의했던 부분을 딕셔너리 형태로 직접 정의해야한다. 'post_list'는 '포스트중 Category.objects.get(slug=slug)로 필터링한 카테고리만 가져와라' 라는 뜻이다. 'categories'는 카테고리 카드를 채워준다. 'no_category_post_count'는 미분류 포스트와 개수를 알려준다. 'category'는 페이지 타이틀 옆에 카테고리 이름을 알려준다.
class Post
ForeignKey가 아니라 ManyToManyField
를 사용해 Tag모델을 연결한다.
{% for p in post_list %}
(..생략..)
{% if p.tags.exists %}
<i class="bi bi-tags"></i>
{% for tag in p.tags.iterator %}
<a href="{{tag.get_absolute_url}}">
<span class="badge bg-success">{{ tag }}</span></a>
{% endfor %}
<br />
{% endif %}
urlpatterns=[
path('create_post/', views.PostCreate.as_view()),
post_form.html
생성{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block my_style%}
<link rel="stylesheet" href="{% static 'css/my_style.css' %}">
{% endblock my_style %}
{% block head_title %}::: Create Post - Blog :::{%endblock%}
{% block main_area %}
<section class="container">
<h1>Create New Post</h1>
<hr />
<form method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form | crispy }}
<button type="submit" class="btn btn-primary float-right">등록</button>
</form>
</section>
{% endblock main_area %}
로그아웃 상태에서는 포스트 작성 페이지에 접근할수 없도록 해야한다.
LoginRequiredMixin
클래스를 추가하면 로그인했을 때만 정상적으로 페이지가 보이게 된다.class PostCreate(LoginRequiredMixin, CreateView):
model = Post
# form 클래스 추가했을경우 제거.
fields = ['title','hook_text','content','head_image','file_upload','category']
class PostCreate(LoginRequiredMixin, CreateView):
model = Post
# form 클래스 추가했을경우 제거.
fields = ['title','hook_text','content','head_image','file_upload','category']
def form_valid(self, form):
current_user = self.request.user
if current_user.is_authenticated and (current_user.is_staff or current_user.is_superuser):
form.instance.author = current_user
return super(PostCreate, self).form_valid(form)
else:
return redirect('blog/')
1) self.request.user = 방문자
2) 방문자가 로그인한 상태(is_authenticated)인지 아닌지 확인
3) 로그인을 한 상태라면 form에서 생성한 instance의 author 필드에 current_user(현재 접속한 방문자)를 담는다.
4) 만약 방문자가 로그인하지 않은 상태라면 redirect() 함수를 사용하여 '/blog/'로 보낸다.