웹 페이지를 관계형 데이터베이스 관점으로 볼 필요가 있다. 관계에는 1:1, 1:N, M:N 관계가 있다. dashboards에서 상세보기 기능은 1:1관계에 해당한다. 사용자의 id값을 통해 detail페이지로 이동했기 때문이다. 이번에 학습할 comment는 1:N관계를 갖는다. 하나의 게시글(1)에는 여러개의 댓글(N)을 입력받기 때문이다.
로직을 한 번 고려해보자. 사용자로부터 image를 입력받기 위해서는 어떻게 했을까? 무언가를 사용자로부터 입력을 받는다는 것은 model을 건드린다는 것이다. image입력은 models.py에서 image를 추가하였다. modelform을 건드리지는 않았다. comment에서는 역시 model에 추가한 뒤, modelform을 적용할 것이다.
on_delete
외래키가 참조하는 객체가 사라졌을 때, 외래키를 가진 객체를 어떻게 처리할 지를 정의한다. 데이터 무결성을 위해서 매우 중요한 설정이다.
게시글이 삭제되면 게시글에 달려있던 댓글들도 삭제된다.
models.py
ForeignKey() 클래스의 인스턴스 이름은 참조하는 모델 클래스 이름의 단수형(소문자)으로 작성해야 한다. dashboard 우리는 dashboard의 기본키를 comment클래스에서 외래키로 참조한다.
외래 키 필드(Comments클래스 내부 필드)의 ForeignKey 클래스를 작성하는 위치는 마지막이다.
이유는 ForeignKey를 먼저 작성하게 되면 참조하는 Model 클래스를 찾을 수 없다. 또한 참조하고 있는 dashboard처럼 항상 단수형 소문자로 작성하는 것을 강력하게 권고한다.
Model 수정 후 python manage.py makemigrations
python manage.py migrate
수행!
이렇게 저장을 한 뒤, admin 페이지에서 댓글 작성을 해보자.
다음과 같이 'dashboards/admin'에 등록!
댓글을 작성하면 모델에 있는 Comment클래스의 필드 이름이 dashboard_id 로 저장이 되는 것을 확인할 수 있다. 이것은 Comment클래스에서 Foreign Key로 참조하고 있는 dashboard필드를 의미한다.
comment.dashboard는 직접참조
dashboard.comment.set_all()은 역참조
현재 comment에서 dashboard를 참조하고 있으니 comment.dashboard는 dashboard의 객체를 말하는 것이고, dashboard.comment.set_all()은 comment의 쿼리셋을 말하는 것이다.
views.py
우선 detail 함수에 comments를 입력받는다. 이는 Model에서 Dashboard를 참조하고 있는 Comment클래스에서 역참조하여 해당 Dashboard의 댓글을 모두 가져온 것이다. 또한 commentsForm은 Comment모델폼에 bootstrap을 적용하기 위해 context로 넘겨준 것이다.
detail.html
view에서 context로 넘겨준 commentsForm을 bootstrap으로 적용하였고 comments(역참조하여 가져온 모든 댓글들)를 for문을 통해 전부 출력하도록 templates을 구성했다.
forms.py
forms.py에서 다음과 같이 Comment모델의 content필드로만 모델폼을 구성했다. (create_at은 넣지 않았다.)
다음과 같이 댓글이 없을 때 '댓글이 없습니다'를 출력해보자!
{% empty %}
태그로 쓸 수 있다.
Admin 페이지에서 댓글을 작성하고 출력까지 해보았다. create Comment를 직접 해보자!
path 작성!
if문 전까지는 기존의 함수 형식과 크게 차이가 없다. if문에서 보통의 경우에는
comment = commentsFrom.save()
형식으로 작성을 했었다. 이러한 경우에는 서버측에서 직접 save를 해줘야한다. 그렇지 않으면 오류가 발생하게 된다.
detail.html
다음과 같이 작성하면 detail페이지에서 직접 댓글을 달 수 있다.