본문 바로가기
WebFramework/Python Django

[Python Django] 10. DTL(Django Template Language)3 - HTML 반복 작업 및 URL 내 특정 값의 변수화

by Rosmary 2024. 4. 12.
728x90
반응형

 

 

 

 

지난 포스팅에 이어 Django DTL에 대한 마지막 포스팅이다. 이번 포스팅에서는 HTML에서 반복이 필요한 작업이 존재할 경우 DTL 태그를 사용하는 방법, 그리고 URL에 기재된 특정 값을 Django 변수로 사용하는 방법에 대해 알아보려한다.

 

 

 

1. DTL 태그를 이용한 반복문

 

이전의 포스팅에서 계속 사용하는 프로젝트 파일을 이번 포스팅에서도 사용한다. 우선 필자는 지난 번, 태어난 년도 입력 시 입력 년도에 태어난 사람의 만 나이와 한국식 나이를 서버에서 반환하는 페이지에 대해 프론트 및 백앤드 제작을 진행했었다. 이번에는 구구단 연산과 관련된 내용을 진행하려는데, 구구단의 경우 사용자가 특정 정수를 입력하면 그 정수의 1~9를 곱한 값을 화면에 출력하도록 만들려고 한다. 그리고 결과가 정렬이 될 수 있도록 table 태그를 활용하여 데이터를 출력하려 한다.

 

 

 

<table> 태그 내부에 들어가는 내용이 2단이라면 아래와 같은 형태로 HTML 태그가 작성되어야 한다.

 

 

 

그러나 구구단 출력에 필요한 결과값 9개 + 단 정보까지 백앤드에서 넘겨주기에는 views.py에서 context 작성이 쉽지도 않을 뿐더러 효율적이지도 않다. 

 

 

 

보통 구구단의 경우 특정 작업이 반복된 결과이므로, 결과값들을 list 나 tuple과 같이 iterable 한 자료형에 넣어 HTML로 전달하면 좋을 듯 하다. 문제는 이 Iterable한 자료형을 HTML에서 어떻게 반복해서 사용할 것이냐인데, Django는 for 태그를 통해 views.py에서 전달되는 Iterable 자료형의 내부 값들을 하나씩 순차적으로 추출할 수 있도록 만들어 놓았다.

 

사용 방법은 Flask Jinja의 for문 statemtent 사용 방법과 동일하다. for 문의 시작은 {% for ITEM in ITERABLE %} 형태로 시작하며, 마지막은 {% endfor %} 코드를 넣어 for 문이 종료됨을 HTML에 알려주면 된다. 

 

하나씩 진행해보자. 먼저 views.py에서 결과로 랜더링 할 HTML과 함께 전송할 데이터를 저장할 HTML부터 만들어보자.

 

 

 

이제 사용자가 /gugu/index.html에서 입력한 정보를 토대로 1~9까지의 곱셈 연산 결과가 리스트 형태로 result.html 파일과 함께 사용자에게 전달된다. 이를 result.html 파일에서 확인해보자.

 

 

 

List 형태의 데이터가 HTML로 잘 전달되는 것이 확인되었으니, DTL의 for 태그를 사용하여 <tr> 및 <td> 반복 태그를 작성해주면 된다. 아래와 같이

 

모양이 좋지는 않은데 디자인 적용이 안 되어 그런 것이니 그냥 넘어가자...

 

DTL에서는 반복문 사용 시, forloop라는 DTL 변수를 사용하여 특정 값의 Iterable 변수 내 index를 반환하도록 만들 수 있다. 위의 코드에서 {{ forloop.counter }}라는 코드가 그 부분인데, 만약 index 값을 0부터 출력하게 만들고 싶다면 {{ forloop.counter0 }}를 사용하면 된다.

 

 

 

참고로 DTL에서 제공하는 IF 조건문 역시 Flask에서 제공하는 if statement와 동일한 방식을 적용하면 된다. 이 부분은 Flask에서도 한 번 소개한 내용이니 이 포스팅에서는 다루지 않는다.

 

 

 

2. URL 내 특정 값을 views.py의 변수로 사용하기

 

필자가 만든 구구단 결과 페이지를 보면, GET으로 통신을 진행해서인지 URL이 조금 지저분하다. 이제 필자는 이를 POST 통신으로 변경하고, 사용자 입력을 거치지 않고 URL 주소만으로도 구구단 결과가 나타나도록 변경해보려한다. 즉, 현재까지는 결과가 192.30.1.3:8000/gugu/result에 출력이 되었지만, 이제 192.30.1.3:8000/gugu/result/3으로 나타나도록 변경해보려고 하는 것이다.

 

먼저 POST 통신부터 수정을 진행한다. 통신과 관련된 부분은 HTML 및 views.py에 코드가 위치하기 때문에 이 부분을 수정하고 HTML은 CSRF 토큰 값을 참조할 수 있도록 DTL 태그를 넣어준다. 

 

 

 

여기까지 수정이 진행된다면, 구구단 검색 시 결과창에 GET의 QueryString 값은 출력되지 않는 것을 확인할 수 있다.

 

 

 

이제 주소창에 사용자가 입력한 단 정보가 들어가도록 만들어보자. 문제는 사용자가 입력하는 단 정보는 언제든지 변경될 수 있는 사항이기 때문에 urls.py에 모든 값을 수동으로 작성하기에는 부담스러워진다. 지금이야 2부터 9까지의 숫자만 입력받는 간단한 구구단 연산이니 큰 문제가 안되지만, 조금 더 복잡한 웹 서버라면 사용자가 입력할 수 있는 모든 값을 고려해서 urls.py 파일을 수동으로 구성하는 것이 그렇게 간단한 문제는 아니다.

 

이럴거면 차라리 컴퓨터 없애고 구석기 시대로 가는게...

 

Django는 urls.py의 path 함수 내에 지정된 URL 경로를 확인할 때 regex 매칭 방식과 유사하게 진행한다. - Django에서는 URL Pattern Matching이라고 한다 - 그 말인 즉, 위의 스크린샷의 URL 마지막 부분이 전부 정수형이므로, 저 부분만 정수로 인식할 수 있는 어떠한 코드를 넣어주면 된다는 의미다. Django에서는 이를 꺽쇠괄호 <>를 사용하여 표시하며, 괄호 내에는 URL에 입력되는 값의 자료형을 작성하면 된다. 

 

 

 

만약 어떤 URL이 192.30.1.3:8000/gugu/result/3으로 들어온다면 Django는 URL 마지막부분의 3을 views.py의 result() 함수에서 사용할 함수 인자라고 인식을 하게 된다. 따라서 views.py의 result 부분에는 이 인자를 받을 함수 인자를 추가로 만들어주어야하며, 인자에 사용할 변수명도 <int>와 맵핑을 시켜주어야 한다. 따라서, urls.py와 views.py는 최종적으로 아래와 같이 수정되어야 한다.

 

 

 

이제 /gugu/result/ URL 뒤에 단 정보를 입력하면 아래와 같이 추가한 단에 대한 구구단 결과가 출력됨을 확인할 수 있다.

 

 

 

 

 


 

이번 포스팅에서 정리하려는 내용은 모두 작성되었지만, redirect를 활용하여 조금 더 안정적인 웹 페이지를 한 번 만들어보려한다. 

 

현재의 상태라면, 구구단을 입력받는 index.html 페이지와 기존의 /gugu/result 페이지로 접속할 경우 동작을 하지 않는데, index.html의 경우, form 태그 내부 action 값이 /gugu/result를 바라보고 있기 때문에 url 맵핑에 실패했기 때문이고, /gugu/result는 urls.py의 urlpatterns에서 값이 사라져 맵핑에 실패했기 때문이다. 그럼, 이전과 같이 사용자가 단 정보를 입력하되, 결과 페이지 URL의 마지막에는 단 정보가 추가되는 형태를 유지하도록 할 수 없을까? 

 

먼저 urls.py 부터 보자. urls.py는 /gugu URL을 views.index 함수를 바라보도록 설정되어 있고, 이는 기존의 index.html을 랜더링 하는 것이므로, index.html 파일부터 작업을 진행하면 된다.

 

 

 

index.html 파일을 보면, 문제가 될 부분이 form 태그 내부의 action 값인데, 이 액션 값은 반드시 사용자가 입력한 단 정보가 url_name 뒤에 명시가 되어야 한다.

 

 

 

그러나 사용자가 입력하는 단 정보는 form 태그 내부의 input에 의해 작성이 되기 때문에 form action에서는 이 값을 직접적으로 참조할 수 있는 방법이 없다. 따라서, 입력값을 별도의 연산을 거치는 view로 연결하고, 이 view에서 결과 페이지를 호출할 수 있도록 로직을 수정해주어야 한다.

 

먼저 사용자로부터 입력받은 값으로 Redirect를 진행할 URL 부터 패턴에 추가해주자. 필자는 이 URL 패턴의 이름을 operator라고 지었고, index.html 역시 이 URL 패턴을 바라보도록 만들었다.

 

 

 

index.html 페이지와 연결된 URL은 views.py의 operate 함수와 연결되어 있다. 따라서 views.py 파일 내에 operate() 함수를 생성하고, 이 함수에서 "/gugu/result/<int:int_input>" 경로로 redirect 할 수 있도록 아래와 같이 코드를 작성한다.

 

 

Redirect의 URL은 urls.py 파일 내 존재하는 패턴인 "result/<int:input_int>"와 일치하기 때문에, 해당 URL 맵핑의 view 함수인 result()를 참조하게 되며, 이 함수의 수행 결과에 의해 result.html 파일이 연산 결과와 함께 사용자에게 반환된다.

 

 

 

코드 수정 결과 아래와 같이 의도한 대로 잘 동작함을 알 수 있다.

 

 

 

조금 더 욕심을 낸다면 페이지가 존재하지 않는 /gugu/result로 직접 접속했을 때, 에러가 발생하지 않도록 수정까지 해보고 싶지만 크게 어려운 내용은 아니라 이번 포스팅에서는 다루지 않고 넘어가려한다.

 

 

 

.

반응형

댓글