일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Django
- 코딩테스트준비
- 파이썬
- git
- 코딩테스트
- 스파르타내일배움캠프TIL
- 그리디
- greedy
- 스파르타내일배움캠프
- API
- 그리디알고리즘
- sort
- 내일배움캠프
- SQL
- programmers
- 장고
- Riot
- 라이엇
- 백준
- drf
- 롤
- java
- 자바
- 알고리즘
- lol
- 프로그래머스
- python
- 탐욕알고리즘
- 리그오브레전드
- github
- Today
- Total
Lina's Toolbox
Django MTV 사용하기 CR (Create, Read) 본문
Django MTV 사용하기 CR (Create, Read)
Woolina 2024. 8. 29. 11:04
이제 우리가 배운 ORM을 쉘이 아닌 , 장고 코드 안에 직접 작성해보자!
실습 준비
/articles/ 로 들어오면 아래의 articles.html 템플릿이 랜더링되어 보이도록 준비
1. urls.py에 추가
path("", views.articles, name="articles"),
2. views.py에 추가
def articles(request):
return render(request, "articles.html")
3. articles.html
{% extends 'base.html' %}
{% block content %}
<h1>Articles</h1>
{% endblock content %}
조회
데이터베이스에서 모든 아티클을 조회해서 /articles/에서 볼 수 있도록 해봅시다!
1. view에서 model에 접근해 모든 아티클 가져오기
2. view에서 가져온 아티클을 template으로 넘기기
airticles의 views.py 변경
from .models import Article
...
def articles(request):
articles = Article.objects.all()
context = {
"articles": articles,
}
return render(request, "articles.html", context)
...
from .models → . 현재 위치 의미 중에 import Article → (다 가져오는게 아니고) article 클래스를 가져온다!
3. template에서 넘어온 context 보여주기
articles.html 변경
{% extends "base.html" %}
{% block content %}
<h1>Articles</h1>
<ul>
{% for article in articles %}
<li>
<div>글 번호 : {{ article.id }}</div>
<div>글 제목 : {{ article.title }}</div>
<div>글 내용 : {{ article.content }}</div>
<br>
</li>
{% endfor %}
</ul>
{% endblock content %}
{{ articles.id }} = {{ articles.pk }} 똑같이 작동(pk(primary key)는 기본키로 id와 동일)
4. view에서 템플릿을 랜더링해서 리턴
새로운 글 작성
새로운 글을 쓰고싶다면, shell을 열고 작성하면 되지만 그러면 너무 불편하겠죠?
클라이언트에서 서버에 데이터를 전송하여 저장하면 편해요!
⇒ form을 이용하면 됩니다!
/articles/new/로 들어오면 아래의 화면이 보이도록 작성해 보세요!
→ 작성된 form을 보내는곳은 /articles/create/입니다.
1. articles의 urls.py에 추가
from django.urls import path
from . import views
urlpatterns = [
path("", views.articles, name="articles"),
path("new/", views.new, name="new"),
path("create/", views.create, name="create"),
path("hello/", views.hello, name="hello"),
path("data-throw/", views.data_throw, name="throw"),
path("data-catch/", views.data_catch, name="catch"),
]
2. articles의 views.py에 추가
...
def new(request):
return render(request, "new.html")
...
3. articles의 templates에 new.html 만들기
{% extends "base.html" %}
{% block content %}
<h1>New Article</h1>
<form action="{% url 'create' %}" method="GET">
<label for="title">제목</label>
<input type="text" name="title" id="title"><br><br>
<label for="content">내용</label>
<textarea name="content" id="content" cols="30" rows="10"></textarea><br><br>
<button type="submit">저장</button>
</form>
{% endblock content %}
- create view에서 데이터 넘겨받기
- 넘겨받은 데이터로 새로운 데이터 생성하기
def create(request):
# GET 방식으로 전달된 데이터를 받아서
title = request.GET.get("title")
content = request.GET.get("content")
# 받은 데이터를 Article 모델을 이용해서 저장
article = Article(title=title, content=content)
article.save()
context = {
"article": article,
}
return render(request, "create.html", context)
3. 글 작성이 잘되었다는 화면(create.html) 보여주기
def create(request):
# GET 방식으로 전달된 데이터를 받아서
title = request.GET.get("title")
content = request.GET.get("content")
# 받은 데이터를 Article 모델을 이용해서 저장
article = Article(title=title, content=content)
article.save()
context = {
"article": article,
}
return render(request, "create.html", context)
🤔 만약 최신순으로 보여주고 싶다면 어떻게 하면 좋을까요?
created_at 을 사용하거나 pk를 사용하여 정렬을 해주면 됩니다!
→ order_by(기준필드) 는 오름차순이 디폴트
→ 내림차순은 기준필드 앞에 - 붙여준다. order_by(-기준필드)
HTTP Method
GET & POST
GET
- 말그래도 원하는 리소스를 가져오는데에 사용합니다.
- 생성할 때도 사용할 수 있지만(로직상 문제는 없지만), 리소스 조회용으로 사용하자는 개발세계에서의 약속입니다.
- DB에 변화를 주지 않는 요청임을 의미합니다.
- Read에 해당합니다.
POST
- 서버로 데이터를 전송할 때 사용합니다.
- 특정 리소스를 생성 혹은 수정하기 위해 사용합니다.
- DB에 변화를 주는 요청임을 의미합니다.
- Create, Update, Delete에 해당합니다.
get 방식은 데이터를 url에 담아 보내기 때문에(쿼리스트링)
→ 바디는 비어있다.
→ 민감한 정보라면 post로 보내는 것이 더 적절!
(그래도 암호화 되는 것은 아니라서 관리자도구를 열면 보이기는 하지만 그래도...)
body에 담아 보내면 훨씬 더 많은 정보를 담아 보낼 수 있음!
articles/templates/new.html
⇒ 일단, 여기서 GET만 POST로 바꿔보면 어떻게 될까요?
⚠️ 오류가 발생합니다!
사이트간 요청 위조 CSRF(Cross-Site-Request-Forgery)
CSRF(Cross-Site-Request-Forgery)
- 유저가 실수로 해커가 작성한 로직을 따라 특정 웹페이지에 수정/삭제등의 요청을 보내게 되는 것입니다.→ 좋은 사이트 서버 입장에서는 어디서 온 요청인지 구분이 필요해요. ⇒ 즉, 정말 유저가 의도한 요청인지 검증이 필요합니다!
- → 아주나쁜사이트.com → 요청 → 좋은사이트.com
🤔 Q) Https 쓰면 막을 수 있지 않아요?
아닙니다 ! CSRF 공격은 인증이 된 상태에서 해커의 의도대로 서버에 요청을 보내게 되는 것으로 HTTPS가 데이터를 암호화하고 중간에서의 공격을 방지하는 것과는 다른 맥락에서 발생합니다.
즉, 이미 유저의 브라우저에서 인증된 요청을 전송하는것으로 추가적인 보안 조치가 필요합니다.
- CSRF Token을 사용해서 막을 수 있습니다.
- 유저가 서버에 요청을 보낼 때 함께 제공되는 특별한 토큰 값으로, 이 토큰은 사용자의 세션과 연결되어 있습니다. 요청이 전송될 때, 함께 제출되며 서버는 요청을 받을 때 이 토큰을 검증하여 요청이 유효한지 확인하는 방식으로 CSRF을 방지합니다.
- 쉽게말해 서로 알아볼 수 있는 임의의 비밀번호를 만들어서 주고 받는다고 생각해주세요!
- 일반적으로 GET을 제외한 데이터를 변경하는 Method에 적용합니다.
Django는 모든게 준비되어 있습니다!
- Django에서는 쉽게 CSRF Token 방식을 구현할 수 있게 template tag로 제공합니다.
get방식으로 받고 create해도 문제는 없지만,
그냥 개발자들 사이의 약속임.
지금까지 우리 코드는 get으로 받아서 db에 create를 해주고 있으니
안좋은 코드였던 것!
👟 이것을 적는 것만으로 어떻게 동작하는 걸까요?
⇒ settings.py의 미들웨어를 봐주세요!
request가 들어오면 setting.py의 Middleare에 있는 것을 위에서부터 하나씩 쭉 통과하며 하나씩 다 처리하며 장고로 들어온다.
그리고 장고에서 처리한뒤 다시 미들웨어를 하나씩 쭉 다 통과하며 response가 나간다.
POST 방식으로 데이터 주고 받기
new.html
{% extends "base.html" %}
{% block content %}
<h1>New Article</h1>
<form action="{% url 'create' %}" method="POST">
{% csrf_token %}
<label for="title">제목</label>
<input type="text" name="title" id="title"><br><br>
<label for="content">내용</label>
<textarea name="content" id="content" cols="30" rows="10"></textarea><br><br>
<button type="submit">저장</button>
</form>
{% endblock content %}
articles/views.py
...
def create(request):
# POST 방식으로 전달된 데이터를 받아서
title = request.POST.get("title")
content = request.POST.get("content")
# 받은 데이터를 Article 모델을 이용해서 저장
article = Article(title=title, content=content)
article.save()
context = {
"article": article,
}
return render(request, "create.html", context)
...
POST 방식 vs GET 방식
- HEADER
HTTP 전송에 필요한 모든 부가정보를 담고있는 부분으로, 메시지 크기, 압축, 인증, 요청 클라이언트(웹 브라우저) 정보, 서버 애플리케이션 정보, 캐시 관리 정보 등등 을 포함하고 있습니다. - BODY
실제 전송할 데이터가 담겨있는 부분으로, 데이터가 없다면 비어있게 됩니다. - HTTP Request는 어떻게 생겼을까?
📎 GET /url/ HTTP1.1
GET(어떤 방식으로 보내는 건지)/ url(어떤 url로 보내는지)?/http(어떤 약속(프로토콜)로 보내는지)
HOST: aidenlim.dev
HOST 사이트주소(도메인)
…
(HEADER)
(공백)
…
(BODY)
…
- HTTP Response
📎 HTTP1.1 200 OK
Date: ….
…
(HEADER)
(공백)
{ status:200, data: “하잉” }
…
(BODY)
📌 요약
- GET은 데이터를 URL에 담아보내고 POST는 BODY에 담아 보내요!
- 따라서 GET은 데이터 전송에 한계가 있으나, POST는 그렇지 않아요!
- POST방식으로 데이터를 전송할 때는 CSRF Token이 필요해요!
실제로 보면
관리자도구에서 보면 우리가 설정해준 적 없는데 hidden 타입으로 crsf 들어가있다! value=에는 난수의 토큰값이 들어가있다.
우린 넣어준 적이 없는데, 서버가 넣어서 클라이언트로 보내준것!
→ 이 form, 정확히 이 사이트에서 보내준 request만 처리할 수 있게함
토큰값(value)는 그때그때 달라지기 때문에 (그때그때 서버가 보내줌) 토큰 탈취가 불가능하다.
→ 보안상 안전!
'스파르타 내일 배움 캠프 AI 웹개발 과정 > Django framework' 카테고리의 다른 글
Django Form (0) | 2024.08.31 |
---|---|
Django MTV 사용하기 RUD (Read, Update, Delete) (0) | 2024.08.30 |
dbdiagram.io: Django 프로젝트에서 ERD 자동으로 그려주는 사이트 (0) | 2024.08.27 |
Django ORM (0) | 2024.08.27 |
Django Model (0) | 2024.08.20 |