본문 바로가기

TIL

[TIL 2024. 04. 17] 개인과제 오류 수정 (2)

게시물 업데이트 오류

게시물 업데이트와 관련해서 urls, views, update.html(template)까지 모두 코드를 작성했는데, 게시물 상세 페이지에서 게시물 수정을 눌러도 업데이트가 제대로 되지 않는 문제가 있었다.

 

이럴 때 문제는 urls설계를 잘못해서 지정을 잘못했거나, view에서 template에서 render()로 넘겨주는 context의 내용이나 template에서 urls와 view로 가는 요청시에 함께 넘겨주는 인자(parameter)에 문제가 있는 경우가 있었어서 이를 위주로 다시 코드를 뜯어봤다.

 

역시나 view에서 template로 함께 넘겨주는 인자에 문제가 있었다.

오류났을 때의 코드
오류수정된 코드

 

기존에는 view함수에서 update.html로 넘겨주는 context에 'form'만 있었다.

 

그런데,

GET요청(게시물 상세페이지의 수정버튼) -> view의 else문에서 처리(수정폼 렌더링) -> update.html에서 POST요청 보냄 -> view의 if문에서 처리(DB 변경)의 처리 흐름상 update.html에서는 article.pk도 POST요청시 인자로 함께 넘겨줘야 하므로 애초에 view에서도 article에 대한 정보를 넘겨줘야 한다.

(update.html에서 다른 view함수로 article이 넘어오는 경우가 없음. 즉, update.html로 render되는 경우는 update view뿐임)


media파일 출력 오류

사용자가 게시물 작성시 업로드한 media파일을 게시물 상세페이지에 출력하는 과정에서 jpg파일이 이상하게 출력되는 문제가 있었다.

 

이미지 출력 오류난 모습


 

 

기본적으로 media파일 사용시에 신경써야 할 것들은 다음과 같다

 

1. config dir/settings.py

MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"

 

2. config dir/urls.py

from django.conf import settings
from django.conf.urls.static import static


if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

 

if문의 의미는 개발단계에서(DEBUG가 True) urlpatterns에 static을 서빙하는 역할을 추가로 부여하는 것이다.

즉, settings.MEDIA_URL인 '/media/'뒤의 url은 document_root에서 찾으라고 장고에게 알려주는 부분이다.

 


3. bash 터미널상

pip install pillow

pip freeze > requirements.txt

 

image 필드에 사용되는 ImageField를 사용하기 위해 pillow라이브러리를 설치하고, pip list에 변화가 있었으므로 다시 pip freeze를 진행한다.


4. POST요청을 보내는 form태그(template) 수정 (templates in app dir)

<form action="" method="POST" enctype="multipart/form-data">
</form>

 

form태그의 enctype속성을 부여하지 않으면 form태그 내의 버튼을 눌러도 작동하지 않는다.

 

이는 데이터 전송 형식을 지정하는 것인데, 기본은 텍스트이지만 위와 같이 "multipart/form-data'로 수정해주면 file,image의 전송이 가능하다.

 

 


5. view 함수 수정 (views.py in app dir)

    if request.method == "POST":
        form = ArticleForm(request.POST, request.FILES)

 

image를 받아서 바인딩 form을 만들기 위해서는 "request.FILES"를 추가해줘야 한다.


6. image 출력하기

{% if article.image %}
		<img src="{{ article.image.url }}">
{% endif %}

 

POST요청의 결과 redirect한 url이 render하는 html에서 image를 출력한다.

단, 객체.속성으로 접근할 때 뒤에 "url"을 붙여줘야 한다.

 

또 게시물 작성과 관련해서 image는 선택사항인 경우가 많아서 나도 Article model의 필드에서 image에는 blank=True로 지정했다. 즉, image를 선택하지 않아도 게시물 생성이 가능하다. 

따라서 만약 if문으로 예외처리를 해주지 않으면 image가 없는 데이터를 조회했을 때 터져버린다..오류발생.

 

참고로 나는 2번 과정을 빠뜨려서 계속 오류가 난 것이었다ㅜㅜ

 

오류수정 후 이미지 출력화면


views.login didn't return an HttpResponse object

로그인 기능을 구현할 때 계속 위와 같은 오류가 나타났다. view함수에도 return문이 다 있었는데도, response반환이 없다는 오류라 영문을 알 수가 없었다..

 

전체 오류 메시지는 다음과 같다.

The view accounts.views.login didn't return an HttpResponse object. It returned None instead.

 

로그인 기능을 만드는만큼 장고에서 제공하는 AuthenticationForm을 사용하고 있었는데, 무심코 request.POST로 바인딩 form을 만들었던게 오류의 원인이었다.

 

AuthenticationForm에서만 유독 바인딩 시에 (data=request.POST)라는 식으로 해야 오류가 없었다.

살펴보니 변수처럼 보여서 의아했더 "data"는 function이었다.

 

오류난 코드
오류수정된 코드

 

 

참고

  • POST와 GET이 모두 처리되는 일반적인 view의 로직흐름
  • 장고가 제공하는 편리한 함수들(자주 사용함)
    • request.user : 모든 템플릿과 views에서 user(로그인한 현재 사용자)에 바로 접근 가능
    • get_user_model() : 특히 custom user model사용시에 유용함
    • get_user