본문 바로가기

Back-end & Server/Django

[Django] 폼(Form)

728x90
반응형

HttpRequeast 

views.py에 정의된 개별 함수들은 HttpRequest 객체(request 매개변수)를 첫 번째 매개변수로 가짐

HttpRequest의 속성 및 메서드

속성/메서드 설명 예제
request.path 전체 경로, 도메인을 포함하지 않고 선행 슬래시를 포함 '/hello/'
request.get_host() 호스트(즉, '도메인', 공통 용어) '127.0.0.1:8000' or 'www.example/com'
request.get_full_path() 경로와 쿼리 문자열(사용할 수 있는 경우) '/hello/?print=true'
request.is_secure() 요청이 HTTPS를 통해 이뤄진 경우 True, 아닌 경우 False True or False

 

요청에 대한 기타 정보 request.META

사용자의 IP 주소와 사용자 에이전트를 포함해 지정된 요청에 대해 사용할 수 있는 모든 HTTP 헤더를 포함하는 파이썬 사전

일반적으로 사용 가능한 사전의 키들은 다음과 같음

  • HTTP_REFERER : 참조 URL
  • HTTP_USER_AGENT : 사용자 웹 브라우저의 사용자 에이전트 문자열
  • REMOTE_ADDR : 클라이언트의 IP 주소

 

모든 요청을 표시하는 작은 보기를 만들어 보자

def allRequest(request):
    req = request.META.items()
    req.sort()
    tmp = '\n'.join([f'<tr><td>{k}</td><td>{v}</td></tr>' for k,v in req])
    html = f'<table>{tmp}</table>'
    return HttpResponse(html)

 

제출된 데이터에 대한 정보

request.GET, request.POST는 각각 GET, POST 데이터에 액세스할 수 있는 사전형 객체임

일반적으로 HTML <form>에서 GET, POST 방식으로 데이터를 제출함

Django는 제출된 데이터를 처리할 때 request.GET, request.POST를 사용해 처리함

# views.py
from django.shortcuts import render
from django.http import HttpResponse as HR

def search_form(request):
    return render(request,'search_form.html')
    
def search(request):
	# POST는 request.GET 대신 request.POST 사용
    if 'txt1' in request.GET:
        message = f'<h1>GET Data => {request.GET["txt1"]}</h1>'
    else :
        message = 'You submitted an empty form'
    return HR(message)
    
# urls.py
from books.views import *
urlpatterns = [
    path('s1',search_form)
    path('search/',search)
]
# search_form.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>폼 테스트</title>
    </head>
    <body>
    	<!-- POST는 get대신 post -->
        <form action="/search/" method="get">
            <input type="text" name="txt1" />
            <input type="submit" value="Search" />
        </form>
    </body>
</html>

 

action="" 하게되면 현재 페이지로 제출

  • POST 방식을 사용하게되면 CSRF 공격의 위험이 있기 때문에 Django에서는 <form> 태그 안{% csrf_token %}을 사용함
# views.py
def current_page(request):
    inputD = ''
    if request.method == 'POST':
        inputD = request.POST['txt']
    else :
        inputD = None
    contexts = {'inputData':None}
    contexts['inputData'] = inputD
    return render(request,'cur_page.html',contexts)
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>폼 테스트</title>
    </head>
    <body>
        <form action="" , method="post">
            {% csrf_token %}
            <table>
                <tr>
                    <th>입력</th>
                    <td><input type="text" name="txt" /></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit" value="입력" /></td>
                </tr>
            </table>
        </form>
        <h1>
            입력된 값 : <span style="color: aquamarine">{{ inputData }}</span>
        </h1>
    </body>
</html>

 

입력양식 만들기

Django에는 django.forms이라는 폼 양식 라이브러리가 존재함

HTML에 대한 Form 클래스를 정의하여 유효성 검사자동으로 HTML을 작성해주기도 함

커뮤니티 규칙에 따르면 forms.py라는 별도의 파일에 Form 클래스를 유지해야 함

  • forms 필드 종류
 

Django 튜토리얼 파트 9: 폼(form)으로 작업하기 - Web 개발 학습하기 | MDN

Creating and handling forms can be a complicated process! Django makes it much easier by providing programmatic mechanisms to declare, render and validate forms. Furthermore, Django provides generic form editing views that can do almost all the work to def

developer.mozilla.org

from django import forms

class LoginForm(forms.Form):
    iD = forms.CharField()
    pW = forms.CharField()

Django는 접근성을 위해 <label> 태그와 함께 각 필드에 레이블을 추가함

기본 출력은 <table> 형식이지만 다른 형식도 존재함

  • <ul> - as_ul() 메소드

  • <p> - as_p()

특정 필드에 대한 HTML을 표시할 수도 있음

 

데이터의 유효성 검사를 위해서는 Form 객체를 만들 때 필드의 이름과 값의 쌍으로 만든 사전을 매개변수로 전달해야함

# python shell
>>> f = LoginForm({'iD':'pupbani','pW':'pupbani123'})

그 후 데이터를 Form 인스턴스와 연결하면 연결된 양식(Bound form)이 만들어짐

# python shell
>>> f.is_bound

연결된 Form에 대해 is_valid() 메서드를 호출해 해당 데이터의 유효성 여부를 확인

>>> f.is_valid()

필드 중 하나인 'iD'를 전달하지 않으면 유효하지 않음(False)

>>> f = LoginForm({'pW':'pupbani123'})
>>> f.is_valid()

사전의 필드 값을 호출하고 errors 속성을 통해 오류 메시지를 가져올 수 있음

Form 프레임워크는 값을 적절한 파이썬 유형으로 변환해 정리할 수도 있음

  • 연결 폼(Contact form)은 문자열 객체 내 '정리(cleaned)'된 문자열만 처리
  • IntegerField 또는 DateField를 사용하는 경우, 양식 프레임워크는 cleaned_data가 주어진 필드에 적절한 파이썬 정수나 datetime.date 객체를 사용

 

필드의 인자(인자들은 적절한 기본값을 가지고 있음)

required - True로 설정되면, 필드를 빈칸으로 두거나 None 값을 줄 수 없게됨
- 기본값(True)은, 빈 칸을 허용하기 위해서는 False
label - HTML에서 필드를 렌더링할때 사용하는 레이블
- 지정되지 않으면, Django는 필드 이름에서 첫번째 문자를 대문자로, 밑줄을 공백으로 변형한 레이블 새로 생성
label_suffix - 기본적으로 콜론(:)이 레이블 다음에 표시
- 다른 문자(들)을 포함한 접미사를 지정할 수 있도록 해줌
initial 폼이 나타날 때 해당 필드의 초기 값
widget - 사용할 디스플레이 위젯
- 폼 양식은 기본적으로 <input type='text'>로 만들어지지만 widget을 사용하면 다른 타입으로 만들 수 있음
help_text 필드 사용법을 보여주는 추가적인 문구
error_messages 해당 필드의 에러 메시지 목록, 필요할 경우 문구를 수정할 수 있음
validators 해당 필드가 유효한 값을 가질 때 호출되는 함수의 목록
localize 폼 데이타 입력의 현지화(localisation)을 허용
disabled 이 옵션이 True일 때 해당 필드를 볼 수는 있지만 편집이 안됨, 기본값 False
max_length 필드의 크기를 제한함

 

예시 : Login 폼

# forms.py
from django import forms

class LoginForm(forms.Form):
    iD = forms.CharField(required=False)
    pW = forms.CharField(widget=forms.PasswordInput,required=False)
from django.shortcuts import render
from mysite.forms import LoginForm as LF

def login(request):
    inputD = []
    if request.method == 'POST':
        form = LF(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            inputD.append(request.POST['iD'])
            inputD.append(request.POST['pW'])
    else :
        form = LF(initial={'iD':'','pW':''})
        inputD = None
    contexts = {'inputData':None,'form':form}
    contexts['inputData'] = inputD
    return render(request,'login.html',contexts)
<!-- login.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>로그인 테스트</title>
    </head>
    <body>
        <form action="" , method="post">
            {% csrf_token %}
            <table>
                {{ form.as_table }}
            </table>
            <input type="submit" />
        </form>
        <h1>
            입력된 값 :
            <ul>
                {% for item in inputData %}
                <li><span style="color: aquamarine">{{ item }}</span></li>
                {% endfor %}
            </ul>
        </h1>
    </body>
</html>

 

728x90
반응형

'Back-end & Server > Django' 카테고리의 다른 글

[Django] 테스팅  (0) 2023.01.22
[Django] 고급 기능들  (0) 2023.01.20
[Django] Admin 사이트  (0) 2023.01.16
[Django] 모델  (0) 2023.01.16
[Django] 템플릿  (0) 2023.01.01