멋쟁이사자처럼 | [대학 11기] 파이썬 Django 실습 강의리뷰 : 챕터 4

Jimin K·2023년 5월 20일
0
post-thumbnail

테킷스쿨에는 멋쟁이사자처럼 [대학11기] 파이썬 Django 실습 강의가 있습니다.
멋쟁이사자처럼 대학 동아리에 소속되어 활동을 시작하며, 이 강의를 수강할 수 있게 되었습니다.
이번에 리뷰하려는 것은 ✨챕터 4 : Template과 View 정복하기 ✨ 입니다.


①Views를 만드는 2가지 방법

MTV 디자인 패턴
Model : 데이터 관리, 데이터베이스와 연결 및 실행
Template : 데이터 출력, 사용자에게 표현 방식 정의
View : 컨트롤러, 비즈니스 로직을 처리

장고 실행 흐름은 아래와 같다.

웹 브라우저 -> url.py -> view -> Model -> View -> Template -> View -> 웹 브라우저

Views 만드는 두 가지 방법으로 FBV, CBV가 있다.
전자는 함수형이고 후자는 클래스형으로 불린다.
전자인 FBV는 구현이 간단하고, 읽기 쉬우며 직관적인 코드로 구성되어있다는 점에서 장점이 있다.
반면 코드의 확장과 재사용이 어렵고, 조건부 분기를 통한 HTTP 메서드 처리가 어렵다.

후자인 CBV는 코드의 확장과 재사용이 용이하며, 다중상속과 Mixin이 가능하다. 내장 class based view 사용 가능하다. 단점은 읽기 어렵고, 복잡하다. 또한 데코레이션 사용 시 함수를 재정의해야 한다는 점에서 FBV와 다르다.

두 가지 방법 중 상황에 따라서 더 적합한 방식을 사용해 개발을 진행하면 된다.

② Function Based View 알아보고 작성하기 (1)

기존의 config > urls.py 파일에서 하나의 url 을 추가하고자 한다.
이를 위해서 posts> views.py 파일 또한 수정을 해주어야 한다.

// config > urls.pu

urlpatterns = [
 path('url/', url_view)
]
// posts > views.py
from django.http import HttpResponse

def url_view(request):
	return HttpResponse('<h1>장고 실습 중</h1>')

그런데 위의 경우에서 HttpResponse 대신에 JsonResponse를 이용할 수 있다.
코드를 수정하면 다음과 같다.

// posts > views.py
from django.http import HttpResponse, JsonResponse

def url_view(request):
	data = {'code' : '001', 'msg' : 'OK'}
    return JsonResponse(data)

전자의 경우의 경우, 페이지 소스코드를 보면 h1이 그대로 보이는 반면, 후자의 경우에는 그대로 {'code' : '001', 'msg' : 'OK'} 가 출력되는 걸 볼 수 있다.

작성한 url을 받는 방법은 아래와 같다.

// posts > views.py

def url_parameter_view(request):
	return HttpResponse()

또한 url도 추가해 준다.

// config > urls.py

urlpatterns = [
	path('admin/', 'admin.site.urls),
 	path('url/', url_view)
    path('url/<str:username>/', url_parameter_view),

]

이렇게 설정하면, 브라우저 실제 창에서
'기본 포트 넘버'/url/
위의 상황에서 아무 문자열을 입력하면, 해당 내용의 텍스트가 적힌 페이지가 창에서 보인다.
또한 아래의 코드를 views파일에 추가하면 콘솔 창에서 key와 value로 입력한 내용이 보인다.

// posts > views.py

def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(username)
    print(request.GET)
    return HttpResponse(username)

③ Function Based View 알아보고 작성하기 (2)

지금 상황에서 views코드와 url코드는 아래와 같다. import문은 생략한다.

// posts > views.py


def url_view(request):
    print('url_view()')
    data = {'code': '001', 'msg': 'OK'}
    return HttpResponse('<h1>url_view</h1>')
    # return JsonResponse(data)

def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(username)
    print(request.GET)
    return HttpResponse(username)
// config > urls.py

urlpatterns = [
	path('admin/', 'admin.site.urls),
 	path('url/', url_view)
    path('url/<str:username>/', url_parameter_view),

]

더 직관적으로 콘솔창에서 key와 value를 보기 위해서는 views코드를 아래와 같이 수정하면 된다.

// posts > views.py

def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(f'username: {username}')
    print(f'request.GET: {request.GET}')
    return HttpResponse(username)

만약 문자열이 아닌 숫자를 입력하고 싶다면, url파일을 아래와 같이 수정한다.

// config > urls.py

urlpatterns = [
	path('admin/', 'admin.site.urls),
 	path('url/', url_view)
    path('url/<int:username>/', url_parameter_view),

]

str을 int로 수정한 것이다.

또다른 함수를 만들어 기존 파일에 추가해 보자먄

// posts > views.py


def url_view(request):
    print('url_view()')
    data = {'code': '001', 'msg': 'OK'}
    return HttpResponse('<h1>url_view</h1>')
    # return JsonResponse(data)


def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(f'username: {username}')
    print(f'request.GET: {request.GET}')
    return HttpResponse(username)
    

def function_view(request):
    print(f'request.method: {request.method}')
    print(f'request.GET: {request.GET}')
    print(f'request.POST: {request.POST}')
    return render(request, 'view.html'

그리고 posts 폴더 내부에 templates 폴더를 새로 생성해 view.html 파일을 임의로 만들어준다. (반드시 templates 으로 폴더 이름이 동일해야 한다.

//posts > templates > view.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>Document</title>
</head>
<body>
    <a href="/fbv/">새로고침</a><br>

    <form action="" method="GET">
        <input type="text" name="var">
        <input type="submit" value="GET 제출">
    </form>

    <form action="" method="POST"> {% csrf_token %}
        <input type="text" name="var">
        <input type="submit" value="POST 제출">
    </form>
    
</body>
</html>

또한 urls 에도 추가한다.

// config > urls.py

urlpatterns = [
	path('admin/', 'admin.site.urls),
 	path('url/', url_view)
    path('url/<int:username>/', url_parameter_view),
	path('fbv/', funtion_view)
]

실행시키면 아래와 같은 결과가 나온다.

(해당 강의 내용 참고)

데이터를 입력받는 세 가지 방법을 지금 배워본 것이다.
다시 정리하면,
첫 번째는 urls.py에서 views에 적힌 함수를 받아오는 것 (url_view )
두 번째는 브라우져 창에서 key=value형태로 데이터를 전달 받는 것 ( url_parameter_view )
세 번재는 폼을 만드는 것이다. (funstion_view)

세개 모두 함수형으로 구성했다.

if로 function_view를 분기처리 하면 아래와 같다.

// posts > views.py


def url_view(request):
    print('url_view()')
    data = {'code': '001', 'msg': 'OK'}
    return HttpResponse('<h1>url_view</h1>')
    # return JsonResponse(data)


def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(f'username: {username}')
    print(f'request.GET: {request.GET}')
    return HttpResponse(username)
    

def function_view(request):
    print(f'request.method: {request.method}')
    if request.method == 'GET':
        print(f'request.GET: {request.GET}')
    elif request.method == 'POST':
        print(f'request.POST: {request.POST}')
    return render(request, 'view.html')

④ Class Based View 알아보고 작성하기

먼저 views 파일 안에서 class 뷰 를 설정하면 아래와 같다.

// posts > views.py


def url_view(request):
    print('url_view()')
    data = {'code': '001', 'msg': 'OK'}
    return HttpResponse('<h1>url_view</h1>')
    # return JsonResponse(data)


def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(f'username: {username}')
    print(f'request.GET: {request.GET}')
    return HttpResponse(username)
    

def function_view(request):
    print(f'request.method: {request.method}')
    if request.method == 'GET':
        print(f'request.GET: {request.GET}')
    elif request.method == 'POST':
        print(f'request.POST: {request.POST}')
    return render(request, 'view.html')
    
class class_view(ListView):
	model = Post
    template_name = 'cbv_view.html'

그리고 templates 폴더 내부에 cvb_view.html 파일 하나를 만들어준다.

// posts >templates > cbb_view.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>Document</title>
</head>
<body>
    {% for object in object_list %}
        {{ object }}
    {% endfor %}
</body>
</html>

또한 url도 추가해준다.

// config > urls.py

urlpatterns = [
	path('admin/', 'admin.site.urls),
 	path('url/', url_view)
    path('url/<int:username>/', url_parameter_view),
	path('fbv/', funtion_view),
    
    path('cbv/', c;ass_view.as_view()),
]

만약, 방금 만든 클래스 기반 뷰를 함수형으로 만들면 아래와 같다.

def funtion_list_view(request):
    object_list = Post.objects.all().order_by('-id')
    return render(request, 'cbv_view.html', {'object_list': object_list})

url도 아래와 같이 추가한다.

    path('fbv/list/', funtion_list_view),

그리고 templates 내부에 posts 폴더를 만들어서 post_list.html 을 만들어 활동 할 수 있다.

⑤ Django Templates Engine 알아보기 (1)

클라이언(브라우저)가 서버의 view에서 요청을 보내고, 서버의 template을 실행시키고 view는 template를 http언어로 번역해서 브라우로 보낸다.

중요한 점은 template은 서버에서 실행한다는 점이다.

template 태그로 여러가지가 있는데 그 예시로
block(자식 템플릿으로 재정의), extends, include(템플릿을 로드), for, if, url 등이 있다.

템플렛 상속은 pyton 상속과 같은 의미인데, 자식에서 작성한 html이 부모의 html 내용으로 들어간다.
header, footer 등의 중복 요소를 줄여 반복성을 줄인다.

template 필터로는 date, default, center, truncatechars, intcomma 등이 있다.
{{ value|필터명:"형식" }} 으로 구성되어있다.

⑥ Django Templates Engine 알아보기 (2)

기존에 posts 즉 앱 단위에서 templates 폴더를 만들어서 작성했다면, 이제는 config 즉 더 큰 프로젝트 단위체서 템플렛을 설정해 보고자 한다.

이를 위해서는 settings 파일을 수정해주어야 한다.

//config > settings.py

...
TEMPLATES = [
'DIRS': [BASE_DIR / 'templates'],
]
...

그리고 config와 동등한 위치에 templates 폴더를 만들고, 그 내부에 posts 폴더를 또 만든다.

그 내부에 4개의 html 파일을 만들어주는데 그 코드는 전부 동일해도 괜찮다.
post_list, post_detail, post_form, post_confirm_delete 이 네 가지 이다.

이어서 views 파일에도 아래의 코드를 추가해준다.

그리고 posts 파일 내에 urls.py 파일을 만드는데 아래와 같은 코드를 작성한다.

이렇게 만든 걸 config 내의 urls.py 파일에 가져와야 한다.

혹시 헷갈릴까봐, 수정한 코드 전문을 첨부한다.

// posts > views.py

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.views.generic.list import ListView
from .models import Post



# 6강 내용
def index(request):
    return render(request, 'index.html')

def post_list_view(request):
    return render(request, 'posts/post_list.html/')

def post_create_view(request):
    return render(request, 'posts/post_form.html/')

def post_detail_view(request, id):
    return render(request, 'posts/post_detail.html/')

def post_update_view(request, id):
    return render(request, 'posts/post_form.html/')

def post_delete_view(request, id):
    return render(request, 'posts/post_confirm_delete.html/')




# 함수를 실행하는  방법
def url_view(request):
    print('url_view()')
    data = {'code': '001', 'msg': 'OK'}
    return HttpResponse('<h1>url_view</h1>')
    # return JsonResponse(data)


# 받는 방법
def url_parameter_view(request, username):
    print('url_parameter_view()')
    print(f'username: {username}')
    print(f'request.GET: {request.GET}')
    return HttpResponse(username)

def function_view(request):
    print(f'request.method: {request.method}')
    if request.method == 'GET':
        print(f'request.GET: {request.GET}')
    elif request.method == 'POST':
        print(f'request.POST: {request.POST}')
    return render(request, 'view.html')


#  클래스 기반 뷰 
class class_view(ListView):
    model = Post
    ordering = ['-id']
    # template_name = 'cbv_view.html'
    
    
def funtion_list_view(request):
    object_list = Post.objects.all().order_by('-id')
    return render(request, 'cbv_view.html', {'object_list': object_list})
// config > urls.py

from django.contrib import admin
from django.urls import include, path
from posts.views import index, url_view, url_parameter_view, function_view, class_view, funtion_list_view

urlpatterns = [
    path('admin/', admin.site.urls),
    path('url/', url_view),
    path('url/<str:username>/', url_parameter_view),
    path('fbv/', function_view),
    
    path('fbv/list/', funtion_list_view),
    path('cbv/', class_view.as_view(), name='cbv'),
    
    path('', index, name='index'),
    path('posts/', include('posts.urls', namespace='posts')),
]

// posts > urls,.py

from django.urls import path
from .views import post_list_view, post_create_view,post_detail_view, post_update_view, post_delete_view

app_name = 'posts'

urlpatterns = [
    path('', post_list_view, name='post-list'),
    path('new/', post_create_view),
    path('<int:id>', post_detail_view),
    path('<int:id>/edit/', post_update_view),
    path('<int:id>/delete/', post_delete_view),
]

⑦ Django Templates Engine 알아보기 (3)

템플렛의 상속에 대해서 알아본다.

html 코드를 작성할 때, 다 똑같이 작성하는 중복되는 부분을 삭제하고자 한다.

config와 동등한 위치에 생성한 templates에 새로운 파일 base.html 파일을 만든다.

block은 상속받은 내용을 어디에 적을지 정의한다.

// templates > base.html


<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} | 라이언그램 </title>
</head>
<body>
    <div>
        {% block content %}
        {% endblock %} 
    </div>
</body>
</html>

그리고 index.html 파일은 아래와 같이 작성된다.

// templates > index.html

{% extends 'base.html' %}
    {% block title %} 인덱스  {% endblock %}
{% block content %}

    <h1>인덱스 화면</h1>
    <ul>
        <li><a href="{% url 'posts:post-list' %}">게시글 목록</a></li>
    </ul>

{% endblock %}

다른 나머지 post_list, post_detail, post_form, post_confirm_delete 도 수정해준다.

⑧ Django Templates를 작성하며 인스타그램 꾸미기 (1)

각 화면의 구조화와 이루어져야 하고, 각각에 들어가는 내용이 구조화 되어야 한다.

인스타그램 화면을 보면, 크개 상단의 카드뉴스 형태화 하단의 나브바로 구성됨을 확인할 수 있다.

이를 본따 index.html 을 아래와 같이 수정할 수 있다.

// templates > index.html

{% extends 'base.html' %}
    {% block title %} 인덱스  {% endblock %}
{% block content %}

<main>
    <div class="card-list">
        <p>추후 수정 </p>
    </div>
    <div>
        <nav class="bottom-menu-group">
            <ul>
                <li></li>
                <li>검색</li>
                <li>글쓰기</li>
                <li>좋아요</li>
                <li>프로필</li>
            </ul>
        </nav>
    </div>
</main>

{% endblock %}

그리고 settings.py 를 수정해준다.

// settings.py

STATIC_URL = 'static/'
STATICFILES_DIRS = [
    BASE_DIR / 'static'
]

이어서 config와 동등한 위치에 static 이란 이름의 폴더를 생성한다.

그리고 base.html을 비롯한 모든 파일에 아래의 코드를 입력한다.

{% load static %}

더불어 넣고 싶은 이미지가 있다면, 이는 static 폴더 안에 icons 폴더를 만들어서 여기에 넣으면 된다.

이 부분은 기존에 작성된 여러 파일과 조각을 합치는 것에 가깝다.
각각에 작성된 css 파일을 가져와 적용하는 방법 등에 집중해서 보면 좋겠다.

내가 원하는 css 파일을 작성하며 실습하는 것도 좋은 방법이라 생각된다.

지금까지의 실습은 위와 같다.

⑨ Django Templates를 작성하며 인스타그램 꾸미기 (2)

완성한 실습은 위와 같다.


더 많은 강의 후기 및 요약 정보는 : https://blog.naver.com/jimin201396

profile
아둥바둥

0개의 댓글