본문 바로가기

Django/따라하는 장고

20. author 속성

질문, 답변을 달면 누가 글을 작성했는지 알려주는 작성자 항목이 필요하다. Question, Answer 모델에 글쓴이 에 해당되는 author 속성을 추가해야한다.

먼저 질문 모델에 추가하기 위해 projects\mysite\pybo\models.py

 

author 필드는 User 모델을 ForeignKey 로 적용하여 선언했다. User 모델은 django.contrib.auth 앱이 제공하는 사용자 모델로 회원 가입시 데이터 저장에 사용했던 모델이다. on_delete=models.CASCADE 는 계정이 삭제되면 이 계정이 작성한 질문을 모두 삭제하라는 의미이다.

모델을 변경한 후에는 반드시 makemigrations 와 migrate 로 데이터베이스를 변경해 주어야한다.

python manage.py makemigrations 명령어를 실행하자.

명령어를 입력하면 옵션을 선택하라는 메세지가 나온다. Question 모델에 author 를 추가하면 이미 등록되어 있던 게시물에 author 에 해당되는 값이 저장되어야하는데, author 에 어떤 값을 넣어야 하는지 모르기 때문이다. 그것에 관해 어떤 옵션을 선택하라는지 묻는것이다.

1번 옵션은 one-off default 값을 제공한다. 현재 NULL 필드(author 필드) 에 값을 제공하겠다는 의미. 2번 옵션은 실행을 취소하고 models.py 에 default 값을 추가 하겠다는 옵션이다. 우리는 1번 옵션을 선택할 것이다.

1번을 입력하면

그렇게 하면 파이썬 셸이 가동된다 기본값을 지금 입력해달라는 뜻이다. 여기서 1을 다시 입력한다.

여기서 입력한 1은 admin 계정의 id 값이다. 따라서 기존 게시물의 author 에는 admin 계정이 등록된것이다. 계정을 만들때마다 id 가 1부터 순차적으로 증가하는데 처음에 만들었던 슈퍼유저 admin 이 1 인것이다.

 

다 했다면 python manage.py migrate 로 데이터베이스에 적용하자.

 

Answer 모델에도 author 속성을 똑같이 추가하자.

그리고 저번처럼 python manage.py makemigrations 명령어로를 한후 옵션을 아까처럼 선택하자.

그 후 python manage.py migrate 명령어를 수행하자.

author 속성에 null 을 허용하려면 

author = models.ForeignKey(User, on_delete=models.CASCADE,

null=True

이렇게 하면된다. 그렇게하면 migrate 할 때 데이터베이스에 null 허용 컬럼으로 생성된다.

 

Question, Answer 모델에 author 속성이 추가되었으므로 질문과 답변 저장시에 author도 함께 저장해야 한다.

projects\mysite\pybo\views.py 파일을 다음과 같이 수정하자. 

답변과 질문의 글쓴이는 현재 로그인한 계정이므로 answer.author = request.user 로 처리했다. request.user 는 현재 로그인한 계정의 User 모델 객체이다. 이제 다시 서버를 시작하고 테스트 하면 잘 된다.

하지만 로그아웃 상태에서 질문 또는 답변을 등록하면 다음과 같은 ValueError가 발생한다.

이 오류는 request.user 가 User 객체가 아닌 AnonymousUser 객체라서 발생한 것이다. 로그인 상태일땐 User 로그아웃일땐 AnonymousUser 이다. 앞에서 author 속성을 정의할 때 User를 이용하도록 했는데 로그아웃시에는 author 에 User 가 아닌 AnonymousUser 가 대입되어 오류가 발생한 것이다.

이를 해결하기 위해선 request.user 를 사용하는 함수에 @login_required 애너테이션을 사용해야 한다. 이 애너테이션이 붙은 함수는 로그인이 필요한 함수를 의미한다.

projects\mysite\pybo\views.py 를 다음과 같이 수정하자.

질문생성과 답변생성함수는 함수내에서 request.user 를 사용하므로 로그인이 필요한 함수이기 때문에 위에 @login_required 어노테이션을 사용했다. 로그아웃상태에서 실행을 하려고 하면 로그인 화면으로 이동한다.

실제로 로그아웃상태에서 질문등록하기를 누르면 로그인 화면으로 이동이 된다. 이 때의 URL 을 확인해보자.

URL을 확인해보면 next 파라미터가 있는데 이는 로그인 성공후 next 파라미터에 있는 URL로 페이지를 이동하겠다는 의미이다. 하지만 실제로 해보면 로그인을 하면 원래 하려던 질문 등록페이지로 안가고 홈페이지로 가진다. 이를 해결하려면 로그인 템플릿에 hidden 타입의 next 항목을 추가해야한다.

projects\mysite\templates\common\login.html 을 다음과 같이 수정하자.

이렇게 하면 로그인 후 next 항목의 URL 로 이동한다.

 

로그아웃시에 질문 작성하기버튼을 눌렀을때의 오류는 해결했지만 로그아웃상태일때 답변을 달려고 할 때 가 있다. 로그아웃 상태에서도 저장하기 버튼을 누르면 로그인 화면으로 자동으로 넘어가지만 문제는 작성해놓은게 사라진다는 점이다. 작성하기 버튼을 눌렀을때 로그인 화면으로 이동하게 하는것보다 아예 로그아웃상태이라면 작성을 못하게 하는게 좋다.

projects\mysite\templates\pybo\question_detail.html 파일을 다음과 같이 수정하자.

의미를 해석하자면 로그인 상태가 아닌 경우 textates 태그에 disabled 속성을 적용하여 입력을 못하게 만들었다. 보면 알겠지만 {% if not user.is_authenticated %} 태그는 현재 사용자가 로그아웃 상태인지를 체크하는 태그이다.

로그아웃상태일때는 답변내용이 사진과 같이 사용하지 못하게 막혀있다. 이 상태에서 답변등록 버튼을 누르면 로그인 화면으로 이동한다. 그리고 로그인을 하면 오류가 발생할것이다. 로그인시 전달된 next 파라미터 때문에 로그인 후에 답변등록 URL 인 /answer/create 가 GET 방식으로 호출되기 때문이다. 하지만 답변등록시 POST 방식이 아닌경우 HttpResponseNotAllowed 오류가 발생하도록 코딩했다 그래서 오류가 발생하는것이다. 이를 해결하기위해

 projects\mysite\pybo\views.py 파일을 다음과 같이 수정하자.

from django.http import HttpResponseNotAllowed 를 삭제하고. else 부분에 form = AnswerForm() 를 추가하자.

이제 로그아웃상태에서 답변등록 버튼을 누른후 로그인을 하면 원래 화면으로 잘 돌아간다.

'Django > 따라하는 장고' 카테고리의 다른 글

22. 질문 수정 및 삭제  (0) 2022.11.18
21. author 표시  (0) 2022.11.17
19. 회원가입  (0) 2022.11.10
18. 로그인 기능  (0) 2022.11.09
17. 템플릿 필터 및 답변 개수 표시  (0) 2022.11.07