본문 바로가기

Web Programming/Django

백엔드_CRUD 실습 3

오늘의 해볼 실습은 CRUD를 마무리하는 작업이다.

보완을 통해서 보다 나은 성능의 CRUD 처리가 가능하게 할 것이다.

 

진행될 작업은 크게 3가지 이다.

 

1. Home 페이지에서 글 최신순 나열

2. CSRF 보안

3. Templates 폴더 정리

 

 

1. Home 페이지에서 글 최신순 나열

일반적으로 웹 페이지 게시판에서 글은 가장 최신의 글이 가장 먼저 보이게 한다.

그래서 해당 페이지로 들어오면 눈에 띌 수 있도록 가장 위에 보여줘야 한다.

 

따라서 글을 최신순으로 나열하는 것은 간단하지만 사용자 편리성을 위해 중요한 부분이다.

이러한 기능을 장고에서는 단 한줄을 통해 쉽게 해결이 가능하다.

# blogProject/blog/views.py

# Create your views here.
def home(request):
    blogs = Blog.objects.all().order_by('-id') # 객체 묶음 가져오기
    return render(request, 'blog/home.html', {'blogs':blogs})
    # render라는 함수를 통해 페이지를 띄워줄 건데, home.html 파일을 띄워줄 것이고 
    # 이 때, blogs 객체도 함께 넘겨주도록 하겠다.

order_by() 라는 함수를 통해 여러 기준을 통해 정렬이 가능하다.

예를 들어, order_by('title') 이렇게 사용하게 되면 title을 기준으로 객체를 정렬해서 가져오게 된다.

 


2. CSRF 보안

웹은 서버와 클라이언트로 구성된 구조이다.

서버는 누구에게나 개방된 공간이라서(port 80) 보안에 대해서 굉장히 민감하다.

쉽게 말해, 우리는 주소창에 naver.com 을 검색하는 것만으로 naver 서버와 소통을 할 수 있다.

따라서 웹 페이지는 누구나 접근이 가능하기에 보안 문제가 중요하다.

 

이 중에서도 CSRF 공격(Cross Site Request Forgery) 은 중요한 문제이다.

CSRF 공격(Cross Site Request Forgery)은 웹 어플리케이션 취약점 중 하나로 인터넷 사용자(희생자)가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격이다.

 

실제 과거 옥션의 1800만명 개인 정보 유출 사고는 CSRF 공격을 당한 것으로 밝혀졌다고 한다. 중국 해커는 직접 서버를 공격하는 대신, 옥션 운영진을 대상으로 악성 코드를 첨부한 메일을 대량으로 유포하였다. 운영자가 메일을 확인한 순간 ID를 얻을 수 있었고, 해커는 이 ID를 이용하여 옥션 서버에 로그인할 수 있었다고 한다.

 

이렇게 중요한 CSRF 공격에 대처하기 위해서 우리는 Token이라는 것을 활용할 예정인데 장고에서는 간단하게 사용가능하다. 

# blogProject/blogProject/settings.py
...
MIDDLEWARE = [
	...
    'django.middleware.csrf.CsrfViewMiddleware',
]

장고에서는 settings.py에 위와 같이 기본적으로 CSRF가 포함되어있다. 우리는 아래와 같이 {% csrf_token %} 이 한 줄만 new와 edit에 작성하면 csrf_token을 통해 CSRF 공격에 대처할 수 있다.

# blogProject/blog/templates/new.html

{% extends 'base.html' %}
{% block content %}
    {% comment %} create url로 보내기 {% endcomment %}
    <form action="{% url 'create' %}"> 
        {% csrf_token %}
        <h4>제목: </h4>
        <input type="text" name="title">
        <br>

        <h4>본문: </h4>
        <textarea cols=40 rows=10 name="body"></textarea>
        <br>

        <input class="btn btn-dark" type="submit" value="제출하기">
    </form>
{% endblock %}
# blogProject/blog/templates/edit.html

{% extends 'base.html' %}
{% block content %}
        
<form action="{% url 'update' blog.id %}">
    {% csrf_token %}
    <h4>제목: </h4>
    <input type="text" name="title" value="{{blog.title}}">
    <br>

    <h4>본문: </h4>
    <textarea cols=40 rows=10 name="body">{{blog.body}}</textarea>
    <br>

    <input class="btn btn-dark" type="submit" value="제출하기">
</form>
{% endblock %}


3. Templates 폴더 정리

우리는 지금까지 특정 blogProject/blog/templates/ 여기 위치에 바로 template 파일들을 작성하였다.

이러한 처리는App이 한개일때는 상관없지만 App이 다수가 되면 views.py에서 파일을 가져올 때 문제를 일으키곤 한다. 
번거롭더라도 Templates 폴더 안에 따로 앱이름 폴더를 만들고 그 안에 template 파일 넣어주도록 하고자 한다.

 

blogProject/blog/templates/blog 폴더 생성!

기존의 Template 파일(new.html, home.html, detail.html, edit.html)을 blog 폴더 밑으로 이동
ex) blogProject/blog/templates/blog/new.html

그리고 views.py 파일도 수정해주도록 한다.

render 함수를 호출하는 render(request, 'new.html') 다음과 같은 부분을

render(request, 'blog/new.html') 으로 수정해주면 된다.

# R - home(전체 글 목록 보기)
def home(request):
    blogs = Blog.objects.all().order_by('-id') # 객체 묶음 가져오기
    return render(request, 'blog/home.html', {'blogs':blogs})
    # render라는 함수를 통해 페이지를 띄워줄 건데, home.html 파일을 띄워줄 것이고 
    # 이 때, blogs 객체도 함께 넘겨주도록 하겠다.
...

# R - detail(글 하나하나 세부정보 보기)
def detail(request, blog_id) : 
    blog_detail = get_object_or_404(Blog, pk= blog_id) # 특정 객체 가져오기(없으면 404 에러)
    return render(request, 'blog/detail.html', {'blog':blog_detail})
    # render라는 함수를 통해 페이지를 띄워줄 건데, home.html 파일을 띄워줄 것이고 
    # 이 때, blog 객체도 함께 넘겨주도록 하겠다.
...

# C - new(새로운 글을 작성할 수 있는 공간 띄워주기)
def new(request):
    return render(request, 'blog/new.html')
...

#  U - edit(기존 글을 수정할 수 있는 페이지 띄워주기)
def edit(request,blog_id):
    blog= get_object_or_404(Blog, pk= blog_id) # 특정 객체 가져오기(없으면 404 에러)
    return render(request, 'blog/edit.html', {'blog':blog})

'Web Programming > Django' 카테고리의 다른 글

Django 회원가입 이메일 인증(SMTP)  (2) 2020.02.09
Like 좋아요 모델 추가하기  (1) 2019.06.25
백엔드_CRUD 실습 2  (4) 2019.05.10
백엔드_CRUD 실습 1  (0) 2019.05.03
AWS_Django 프로젝트 배포하기  (0) 2019.03.05