2023. 12. 2. 22:48ㆍWeb/Flask
회원가입, 로그인, 로그아웃 기능이 완성돼서 질문, 답변을 "누가" 작성했는지 알 수 있게 됐다
이제 기능을 조금씩 다듬어서 완벽하게 만들어 보자
여기서는 Question, Answer 모델을 수정하여 "글쓴이"에 해당하는 user 속성을 추가할 것이다
SQLite 설정 수정하기
SQLite 데이터베이스는 ORM을 사용할 때 몇 가지 문제점이 있다
이것은 SQLite 데이터베이스에만 해당하
PostgreSQL이나 MySQL 등의 다른 데이터베이스와는 상관없는 내용이다
pybo/__init__.py 파일을 다음과 같이 수정해보자
이와 같이 수정하면 데이터베이스의 프라이머리 키, 유니크 키, 인덱스 키 등의 이름이 변경되므로
flask db migrate 명령과 flask db upgrade 명령으로 데이터베이스를 변경해야 한다
Question 모델에 글쓴이 추가하기
아래와 같이 글쓴이 정보를 Question 모델에 추가하기 위해 user_id, user 속성을 추가하자
user_id 속성은 User 모델을 Question 모델과 연결하기 위한 속성이고
user 속성은 Question 모델에서 User 모델을 참조하기 위한 속성이다
리비전 파일 생성하기
모델을 수정했으니 flask db migrate 명령을 실행해서 리비전 파일을 생성해보자
리비전 파일 적용하기
flask db upgrade 명령을 수행하자
그런데 오류가 발생했다
그 이유는 "user_id 속성이 Null을 허용하지 않기 때문"이라고 한다
Question 모델 데이터를 여러 건을 저장했었는데
그 데이터에는 user_id 속성의 값이 없다
변경된 모델은 이를 허용하지 않으므로 오류가 발생한 것이다
기존에 이미 저장되어 있던 데이터들 때문에 발생한 오류인듯하다
flask db upgrade 명령 오류 해결하기
이 문제를 해결하려면 아래와 같은 과정을 거쳐야 한다
어떤 모델에 nullable=Flase 인 속성을 추가하고자 할 때 어쩔수 없이 거져야 하는 과정이다
1. user_id의 nullable 설정을 False 대신 True로 바꾸기
2. user_id를 임의의 값으로 설정하기(여기서는 1로 설정)
3. flask db migrate 명령, flask db upgrade 명령 다시 실행하기
4. user_id의 nullable 설정을 다시 False로 변경하기
5. flask db migrate 명령, flask db upgrade 명령 다시 실행하기
nullable=True
우선 user_id 속성의 nullable=False를 nullable=True로 변경해보자
그리고 user_id 속성의 기본값을 1로 설정하기 위해 server_default='1'을 입력하자
여기서 server_default에 지정한 '1'은 최초로 생성한 User 모델 데이터의 id 값을 의미한다
기존에 저장된 Question 데이터의 user_id값을 설정하기 위해서 server_default='1'이라는 속성을 추가했다
리비전 오류 확인하기
이제 다시 flask db migrate 명령을 수행해 보자
하지면 여전히 오류가 발생한다
이유는 이전의 migrate 명령은 제대로 수행되었지만 upgrade를 실패하여
정상으로 종료되지 않았기 때문이다
최종 리버전
flask db heads 명령으로 현재 migrate 작업의 최종 리비전을 확인해 보자
현재 리버전
flask db current 명령으로 현재 시점의 리비전을 확인해 보자
결과를 보면 알겠지만 "현재 시점의 리비전"과 "최종 리비전"이 같지 않다
2개의 리비전이 다른 이유는 migrate 이후 upgrade를 실패했기 때문이다
때문에 migrate 명령을 수행할 수 없는 것이다
둘이 일치해야 migrate 작업을 진행할 수 있다
현재 리버전을 최종 리버전으로 변경하기
앞에서 설명했듯 migrate 작업을 계속 진행하려면 flask db stamp heads 명령을 사용하여
현재 리비전을 최종 리비전으로 되돌려야 한다
리비전을 변경한 뒤 다시 flask db current 명령을 수행하자
현재(current) 리비전이 최종(head) 리비전으로 되돌려진 것을 확인할 수 있다
migrate, upgrade 다시 입력하기
다시 flask db migrate 명령과 flask db upgrade 명령을 입력해 보자
오류 없이 잘 동작한다
이제 데이터베이스에는 Question 모델 데이터 모두 user_id 속성에 '1'이 저장된다
nullable=False
이제 비로소 Question 모델의 user_id 속성을 nullable=True에서 nullable=False로 변경할수 있다
그리고 server_default는 필요하지 않으므로 제거하자
코드를 수정하고 flask db migrate, flask db upgrade 명령을 입력하자
지금까지 이미 데이터베이스에 저장된 데이터와 이와 관련된
모델이 변경되었을 때 처리하는 방법을 알아보았다
여기서는 모델 속성에 nullable=False를 설정하는 방법을 알아보았다
migrate 명령을 사용하다 보면 뭔가 꼬이는 현상이 종종 발생한다
이럴 때는 현재 데이터베이스의 변경 내역을 자세히 봐야한다
Answer 모델에 글쓴이 추가하기
Answer 모델도 같은 방법으로 user_id 속성을 추가하자
user_id 속성에 nullable=True를 설정했다
실습하면서 nullable=False 지정은 고생길이라는 것을 훤히 알았을 것이므로
nullable=True, server_default='1'이라고 설정하여 기본값을 저장한 다음에 진행하자
migrate 명령과 upgrade 명령을 입력하자
Answer 모델에서 server_default는 제거하고 nullable=False로 변경하자
다시 migrate, upgrade 명령을 순서대로 입력하자
오류없이 잘 처리될 것이다
답변 등록
답변 등록시 글쓴이를 저장하자
g.user는 세션에 저장된 사용자 정보 데이터이다
질문 등록
질문 등록도 똑같은 방법으로 수정하자
이제 로그인 후에 질문과 답변을 등록해 보자
문제 없이 잘 등록될 것이다
login_required
로그아웃 상태에서 질문 또는 답변을 등록하면 아래와 같은 오류가 발생한다
오류가 발생한 이유는 로그아웃 상태에서는 g.user의 값이 None이기 때문이다
이 문제를 해결하려면 로그아웃 상태에서는 질문 또는 답변을 작성하려고 할 때 로그인을 먼저 진행할 수 있도록 로그인 페이지로 리다이렉트해야 한다
그렇게 하려면 모든 질문, 답변 등록 함수의 시작 부분에 세션 값을 체크하여
사용자 정보가 없을 경우 로그인 페이지로 리다이렉트하는 코드를 추가해야 한다
이런식으로 코드를 작성하면 코드가 중복되므로 비효율적이다
이것 해결하는 방법이 있다
@login_required 데코레이터
auth_views.py 파일에 login_required라는 이름의 데코레이터 함수를 아래와 같이 만들어 보자
코드에서 보듯 데코레이터 함수는 기존 함수를 감싸는 방법으로 간단히 만들 수 있다
이제 라우팅 함수에 @login_required 애너테이션을 지정하면 login_required 데코레이터 함수가 먼저 실행될 것이다
login_required 함수는 g.user가 있는지를 조사하여 없으면
로그인 URL로 리다이렉트 하고 g.user가 있으면 원래 함수를 그대로 실행할 것이다
요청 방식이 GET인 경우에는 로그인 후에 원래 가려던 페이지로 다시 찾아갈수 있도록
로그인 페이지에 next 파라미터를 전달했다
따라서 로그인 함수도 next 파라미터를 처리하기 위해 다음과 같이 수정해야 한다
로그인시 next 파라미터 값이 있으면 읽어서 로그인 후
해당 페이지로 이동하고 없으면 메인 페이지로 이동하게 했다
@login_required 적용하기
로그인이 필요한 함수에 @login_required 데코레이터를 적용해 보자
우선 질문 등록 함수에 적용
답변을 등록하는 함수에도 적용
이제 로그아웃 상태에서 질문 또는 답변 등록을 시도하면 로그인 화면으로 리다이렉트될 것이다
로그아웃 상태에서 답변 등록 불가능하게 만들기
현재 질문 등록은 로그아웃 상태에서는 아예 글을 작성할 수 없어서 만족스럽다
하지만 답변 등록은 로그아웃 상태에서도 글을 작성할 수 있다
물론 답변 작성 후 <저장하기>를 누르면 자동으로 로그인 화면으로
이동되므로 큰 문제는 아니지만 작성한 답변이 사라지는 문제가 있다
작성한 글이 사라지는 문제를 해결하려면 로그아웃 상태에서는 아예 답변 작성을 못하게 막는 것이 좋을 것이다
답변 작성 템플릿에서 textarea 엘리먼트가 로그인 상태가 아닌 경
disabled를 지정하여 입력 자체를 하지 못하도록 아래와 같이 수정하자
이제 disabled 설정으로 textarea 엘리먼트가 비활성화될 것이다
'Web > Flask' 카테고리의 다른 글
[Flask] 3-10 게시물 수정 & 삭제 (2) | 2023.12.03 |
---|---|
[Flask] 3-9 글쓴이 표시하기 (1) | 2023.12.03 |
[Flask] 3-7 로그인과 로그아웃 (0) | 2023.12.02 |
[Flask] 3-6 회원가입 (0) | 2023.12.02 |
[Flask] 3-5 질문에 달린 답변 개수 표시하기 (0) | 2023.12.02 |