2. django 요청 보내고 받기 GET,POST

검색 기능 구현 확인

  1. form 태그 안에 input 값의 ‘key’=value 로 데이터를 주고 받는 것을 확인해 보자.
  2. view.py ==> urls.py ==> templates 순으로 작업하자
   #view.py
   def throw(request):
       return render(request, 'throw.html')
   #urls.py
   urlpatterns = [
       path('throw/', views.throw),]
   <!-- throw.html-->
   
  1. 데이터 주고 받기

throw

   # views.py
   def throw(request):
       return render(request, 'throw.html')
   #urls.py
   path('throw/', views.throw),
   <!-- throw.html -->
   <form action="/catch/" method="GET"> 
     <label for="message">Throw</label>
     <input type="text" id ="message" name="message"> <!-- name 값으로 데이터 주고 받는데 key값이다. id는 java 이용시 활용-->
     <input type="submit"> <!-- action쪽으로 데이터를 전달-->
   </form>
`catch`
   # views.py 
   def catch(request):
       # pprint(request)   # 터미널에서 정보를 어떻게 넘겨주는지 확인하는 명령어
       # pprint(request.scheme) 'http' [16/Aug/2019 10:58:59] "GET /catch/?message=1 HTTP/1.1" 200 50
       # pprint(request.path) '/catch/'[16/Aug/2019 10:57:35] "GET /catch/?message=1 HTTP/1.1" 200 50
       # pprint(request.method) 'GET' [16/Aug/2019 10:58:34] "GET /catch/?message=1 HTTP/1.1" 200 50
       # pprint(request.GET) # {Querydic:value} 출력
       # pprint(request.META) #전체를 프린트
       message = request.GET.get('message')
       context = {'message': message,}
       return render(request, 'catch.html', context)
   
   <!-- catch.html -->
   <h1>catch 에서 보낸 를 받았습니다.</h1>
  1. ASCII ART 폰트로 출력하기

    art 보내주는 역할

    def art(request):
        return render(request, 'art.html')
     path('art/', views.art),
    
    <form action="/result/" method="GET">
      <label for="word">영단어를 입력하세요</label>
      <input type="text" id="word" name="word">
      <input type="submit" value="생성하기">
    </form>
    

    result 받는 역할

    def result(request):
        #1. art 에서  form으로 보낸 데이터를 받는다.
        word = request.GET.get('word')
       
        # 2. ARTII API 폰트 리스트로 요청을 보내 응답을 text로 받는다. requests 라이브러리 다운로드필요
        fonts = requests.get('http://artii.herokuapp.com/fonts_list').text # .text 는 뷰티파이에서 ...
        # print(fonts)
       
        # 3. str을 list로 바꾼다.
        fonts = fonts.split('\n')
       
        # 4. fonts list 안에 들어있는 요소 중 하나를 선택해서 변수에 저장 #폰트를 변경해주는 역할
        font = random.choice(fonts)
       
        # 5. 위에서 만든 word와 font를 가지고 다시 요청을 만들어서 보낸 응답결과를 받는다.
        response = requests.get(f'http://artii.herokuapp.com/make?text={word}&font={font}').text
       
        context = {'response': response,}
        return render(request, 'result.html', context)
    
    <h1>ASCII ART 에 오신걸 환영 합니다. :)</h1>
       
    <pre></pre> <!--  원형 그대로 출력하는 태그 pre-->
    
  2. POST 로 데이터 보내기

    1. 데이터 베이스를 수정하고 불러올 수 있다.

    2. Form data라는 바디를 확인 할 수 있다.

    3. user_new 보내기 역할 (urls 코드는 생략한다.)

      def user_new(request):
          return render(request, 'user_new.html')
      
      <form action="/user_create/" method="POST"> <!--post 방식은 action="/*/" 역슬래쉬 꼭 붙여주기-->
        <label for="name">아이디</label>
        <input type="text" id="name" name="name"><br>
        <label for="pwd">패스워드</label>
        <input type="password" name="pwd" id="pwd">
        <input type="submit" value="가입">
      </form>
      
    4. user_create 받는 역할 (urls 코드는 생략한다.)

      def user_create(request):
          name = request.POST.get('name')
          pwd = request.POST.get('pwd')
          context = {'name': name, 'pwd': pwd,}
          return render(request, 'user_create.html', context)
      
      <p>아이디 : </p>
      <p>패스워드 : </p>
      

      forbbiden 오류창이 뜬다.

      인증이 필요함

    5. csrf token ( Framework를 쓰는 이유 : 보안처리를 해줌)

      MIDDLEWARE = ['django.middleware.csrf.CsrfViewMiddleware', # 보안 검증 ]

      사이트간 위조 방지 (토큰 값도 함께 넘어감)

      <form action="/user_create/" method="POST">
        <!-- csrf_token --> <!-- 위조방지 토큰 -->
        <label for="name">아이디</label>
        <input type="text" id="name" name="name"><br>
        <label for="pwd">패스워드</label>
        <input type="password" name="pwd" id="pwd">
        <input type="submit" value="가입">
      </form>
      

      정리 : csrf 사이트 간 요청 위조

      • 웹어플리케이션 취약점 중 하나로 사용자가 자신의 의도와 무관하게 공격자가 의도한 ㅐㅇ동을 해서 특정 웹페이지의 보안을 무력화 시키거나, 수정, 삭제 등의 강제적인 작업을 하게하는 공격방법.
      • django는 최소한의 안전장치를 위해 자신이 부여한 랜덤 hash 값을 token으로 부여한다. 이 token 값이 없는 요청은 잘못된 요청이라고 판단하여 접근을 거부한다.(403 error)

2. Static 정적파일

  • image/css/js 파일과 같이 해당 내용이 고정되어 응답을 할 때 별도의 처리 없이 그대로 보여주면 되는 파일들

    ex)

      
    {% load static %}   <!-- load 를 요런식으로 무조건 써야함. -->
      
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <link rel="stylesheet" href="{% static 'stylesheet/style.css' %}"> <!-- staic 안에 ''에 작성 -->
    </head>
    <body>
      
    <h1>Static 파일 실습</h1>
    <img src="{% static 'images/images.jpg' %}" alt="static_img">
        
    </body>
    </html>
    

3. URL 로직 분리

프로젝트 url 순서도

url 파일들

  • 각각의 urls 파일 코드를 비교하여 보자.

    # 프로젝트(django_intro) urls
      
    from django.contrib import admin
    from django.urls import path, include
    # from pages import views # 생성한 앱 pages 폴더 안의 views.py를 가져옴
      
      
      
    urlpatterns = [
        path('utilities/', include('utilities.urls')),
        path('pages/', include('pages.urls')),  # include('(앱파일명).urls') 
        path('admin/', admin.site.urls),
    ]
    
    # 앱(pages) urls
    from django.urls import path
    from . import views # . 은 현재 폴더
    urlpatterns = [
        path('index/', views.index), #  url 경로 마지막에 / 를 붙이는 습관
        path('introduce/<name>/<int:age>/', views.introduce),
        path('dinner/', views.dinner),
        path('image/', views.image),
        path('hello/<name>/', views.hello),
        path('times/<int:num>/<int:num2>/', views.times),
        path('area/<int:r>/', views.area),
        path('template_language/', views.template_language),
        path('isitgwangbok/', views.isitgwangbok),
        path('catch/', views.catch),
        path('throw/', views.throw),
        path('art/', views.art),
        path('result/', views.result),
        path('user_new/', views.user_new),
        path('user_create/', views.user_create),
        path('static_example/', views.static_example),
    ]
    
    #앱(utilities) urls
    from django.urls import path
    from . import views
      
    urlpatterns = [
        path('index/', views.index),
    ]
      
    

4. Django namespace

4.1 template / static

  • 앱 상관 없이 Templates(.html파일 모은 장소)들을 한곳에 모아서 불러온다. 만약 templates의 html 파일명이 겹치면 앱 등록시 최상단에 입력된 순서먼저 불러온다. 네임 오류이다.

  • 장고는 서버 실행시 한곳에 모든 파일들을 한 곳에 불러오므로, 앱별로 해당 영역들을 구별해야 한다. (중간네임 스페이스를 지정해줘야 한다.)

제목 없는 프레젠테이션

  • Namespace 나누기 전에 setting.py>INSTALLED_APPS의 최상단에서 매칭 한다. 그래서 utilitiesindex먼저 불러오고 마친다.

5. Template Inheritance (상속)

base 템플릿 만들고 그 녀석을 다른 녀석들의 속성으로 부여 하는 방법.

  • 경로 생성

    # settings.py
    ...
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ...
    TEMPLATES = [
        {
             
            'DIRS': [os.path.join(BASE_DIR, 'django_intro', 'templates')], #추가 경로 생성 가능한 곳.
             
        },
    ]
    
  • index. html 에 base.html (엄마템플릿)속성 부여

    {% extends 'base.html' %} <!-- extend가 모든 경로보다 위로 가야 합니다. 최상단에 위치-->
      
    <!DOCTYPE html>
    <html lang="ko">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      {% block content %}
      <h1>Hi django!!</h1>
      {% endblock content %}
      
    </body>
    </html>
    
  • {% extends ‘base.html’ %} 무조건 맨 위에
  • {% block content %}
  • {% endblock %}