์ด์ ๋ ๋ณธ๊ฒฉ์ ์ผ๋ก CRUD๋ฅผ ๋ฐฐ์ธ ์์ ์ ๋๋ค. CRUD๋ ๋๋ถ๋ถ์ ์ปดํจํฐ ์ํํธ์จ์ด๊ฐ ๊ฐ์ง๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ธ Create(์์ฑ), Read(์ฝ๊ธฐ), Update(๊ฐฑ์ ), Delete(์ญ์ )๋ฅผ ๋ฌถ์ด์ ์ผ์ปซ๋ ๋ง์ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ด๋ฏธ ๋ง๋ค์๋ Blog ๊ฐ์ฒด๋ค์ Read๋ก ๋จผ์ ํ์ธํด๋ณด๊ณ , Create๋ฅผ ๋ฐฐ์๋ณด๊ฒ ์ต๋๋ค.
๊ทธ ์ ์ GET๋ฐฉ์๊ณผ POST๋ฐฉ์์ ๋ํด ๋จผ์ ์ง์ด๋ณด๊ณ ๋์ด๊ฐ๊ฒ์.
GET๋ฐฉ์์ ๋ฐ์ดํฐ๋ฅผ ์ป๊ธฐ ์ํ ์์ฒญ์ ๋๋ค. URL์ ๋ณ์๋ฅผ ํํจ์์ผ ์์ฒญํ๊ฒ ๋๋ฏ๋ก, ๋ฐ์ดํฐ๊ฐ ๋ ธ์ถ๋์ด ๋ณด์์ ์ทจ์ฝํ์ฃ . e.g. /hello/test.php?name1=value1&name2=value2
๋ฐ๋ฉด POST๋ฐฉ์์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์์ฒญ์ ๋๋ค. ๋ฐ์ดํฐ๊ฐ ๋ณธ๋ฌธ(BODY)์ ํฌํจ๋๋ฏ๋ก ๋ฐ์ดํฐ๊ฐ URL์ ๋ ธ์ถ๋์ง ์์ ๊ธฐ๋ณธ์ ์ธ ๋ณด์์ด ๊ฐ๋ฅํฉ๋๋ค. CSRF ๊ณต๊ฒฉ ๋ฐฉ์ง๊ฐ ๊ฐ๋ฅํฉ๋๋ค. CSRF ๊ณต๊ฒฉ(Cross Site Request Forgery)์ ์น ์ดํ๋ฆฌ์ผ์ด์ ์ทจ์ฝ์ ์ค ํ๋๋ก ์ธํฐ๋ท ์ฌ์ฉ์(ํฌ์์)๊ฐ ์์ ์ ์์ง์๋ ๋ฌด๊ดํ๊ฒ ๊ณต๊ฒฉ์๊ฐ ์๋ํ ํ์(์์ , ์ญ์ , ๋ฑ๋ก ๋ฑ)๋ฅผ ํน์ ์น์ฌ์ดํธ์ ์์ฒญํ๊ฒ ๋ง๋๋ ๊ณต๊ฒฉ์ ๋๋ค. CSRF ๊ณต๊ฒฉ์ ๋ฐฉ์ดํ๊ธฐ ์ํ ๋ค์ํ ๋ฐฉ๋ฒ์ด ์์ง๋ง Django์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก csrf token์ ์ด์ฉํ๋ฉฐ, POST ์์ฒญ์ ๋ํด์๋ง csrf token์ ๋ฐ๊ธํ๊ณ ์ฒดํฌํฉ๋๋ค.
from django.shortcuts import render
from .models import Blog # Blog import ํด์ฃผ๊ธฐ
def showmain(request):
blogs = Blog.objects.all() # blogs๋ผ๋ ๋ณ์์ Blog์ ๋ชจ๋ ๊ฐ์ฒด๋ค ๋ด๋๋ค.
return render(request, 'main/mainpage.html',{'blogs':blogs})
models.py์ Blog
๋ฅผ ๋ง๋์ import ํด์ฃผ์ด์ผ ์ธ์ํ ์ ์์ต๋๋ค.
๊ทธ ํ showmain
ํจ์๋ฅผ ์์ ํด์ค๊ฒ์. ๋จผ์ blogs
๋ผ๋ ๋ณ์์ Blog์ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋ด์ต๋๋ค. ๊ทธ ๋ค์ main
์ฑ์ mainpage.html
์ blogs
๋ผ๋ ์ด๋ฆ(key)์ผ๋ก ์๊น Blog์ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋ด์๋ blogs
(value)๋ฅผ ๋ณด๋ด์ค๋๋ค.
๐ก render์ ์ธ ๋ฒ์งธ ์ธ์๋ก๋ Python์ ๋์
๋๋ฆฌ(dictionary) ํ์
์ ๊ฐ์ ๋ฃ์ด์ค์ผ ํฉ๋๋ค. ๋์
๋๋ฆฌ ํ์
์ {'key':value}
์์ฃ . ์ด ๊ณผ์ ์ ํด์ผ mainpage.html
์์ blogs
๋ฅผ ์ธ์ํ ์ ์์ต๋๋ค.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>2021 Dongguk Likelion 3rd session</h1>
<a href="{% url 'first' %}">first</a>
<a href="{% url 'second' %}">second</a>
<img src="{% static 'images/image01.jpg' %}">
<h1>๊ธ ๋ชฉ๋ก</h1>
<div>
{% for blog in blogs %} <!-- blogs์ ๊ฐ์ฒด๋ค์ blog๋ผ๋ ์ด๋ฆ์ผ๋ก ํ๋์ฉ ๊บผ๋ด ๋ฐ๋ณตํ๋ค. -->
<div>
<h3>
{{blog.title}} <br> <!-- ๊ทธ ๊ฐ์ฒด ํ๋ blog์ ์์ฑ title์ ๋์์ค๋ค. -->
{{blog.writer}}<br> <!-- ๊ทธ ๊ฐ์ฒด ํ๋ blog์ ์์ฑ writer๋ฅผ ๋์์ค๋ค. -->
{{blog.body}} <!-- ๊ทธ ๊ฐ์ฒด ํ๋ blog์ ์์ฑ body๋ฅผ ๋์์ค๋ค. -->
</h3>
</div>
{% endfor %}
</div>
{% endblock %}
shomain
ํจ์์์ blogs
์ Blog์ ๋ชจ๋ ๊ฐ์ฒด๋ค์ ๋ด์์ ๋ณด๋ด์ฃผ์์ต๋๋ค. ์ด์ ์ด ๊ฐ์ฒด๋ค์ for๋ฌธ์ ํตํด ํ๋ฉด์ ํ์ํด์ค๊ฒ์. blogs
์ ์ฌ๋ฌ ๊ฐ์ฒด๋ค์ ํ๋์ฉ ๊บผ๋ด blog
๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ด์์ ๋ฐ๋ณต๋ฌธ์ ๋๋ ค์ค๋๋ค.
โ๏ธ ํ
ํ๋ฆฟ ํ๊ทธ
base.html ์์, url, include ํ ๋ ๋ง์ด ๋ดค๋ ํ
ํ๋ฆฟ ํ๊ทธ {% %}
์
๋๋ค. ์ง๊ธ๊น์ง ์ฌ์ฉํ๋ ํ
ํ๋ฆฟ ํ๊ทธ๋ ๋ซ์ง ์์๋ ๋์ง๋ง, for
, if
๋ฌธ์ ๋ฐ๋์ ๋ซ์์ฃผ์ด์ผํฉ๋๋ค.
โ๏ธ ํ
ํ๋ฆฟ ๋ณ์
html์ ๋ณ์๊ฐ ํ์๋๊ฒ ํ๋ ค๋ฉด ํ
ํ๋ฆฟ ๋ณ์์ธ ์ค๊ดํธ 2๊ฐ {{ }}
๋ฅผ ์ฌ์ฉํฉ๋๋ค. 3์ฃผ์ฐจ ์ธ์
์์ ํ
ํ๋ฆฟ ์ธ์ด์๋ ๋ณ์, ํํฐ, ํ๊ทธ, ์ฃผ์ 4๊ฐ์ง๊ฐ ์๋ค๊ณ ๋ฐฐ์ ์ฃ ? ๊ทธ ์ค ๋ด์ฉ์ ๊ฐ์ ธ์ค๋ ์ญํ ์ ํ๋ ํ
ํ๋ฆฟ ๋ณ์์
๋๋ค. ๊ฐ์ฒด์ ์์ฑ์ ์ ๊ทผํ๋ ค๋ฉด ์ด์ ์ shell์์ ORM์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ฒ๋ผ .
์ ์ฌ์ฉํด์ฃผ๋ฉด ๋ฉ๋๋ค.
๋ณธ๋ฌธ ๋ด์ฉ์ด ๋๋ฌด ๊ธธ๋ฉด ์๋ถ๋ถ ๋ช๊ธ์๋ง ๋ณด์ด๊ฒ ํ ์ ์์ต๋๋ค. models.py์ Blog
ํด๋์ค๋ก ๋ค์ ๊ฐ์ summary
ํจ์๋ฅผ ์ถ๊ฐํด์ค๋๋ค.
class Blog(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=200)
writer = models.CharField(max_length=100)
pub_date = models.DateTimeField(auto_now_add=True)
body = models.TextField()
def __str__(self):
return self.title
def summary(self):
return self.body[:20] # ๊ฐ์ฒด ์๊ธฐ์์ ์ body์์ฑ์ ์ฒ์(0)๋ถํฐ 19๊น์ง slicingํ์ฌ ๋ฆฌํด
โ๏ธ Python slicing
A[start:end:step]
start
: ์์ ์์น, end
: ๋๋ผ ์์น, step
: ๊ฐ๊ฒฉ(๋ณดํญ)
index๋ 0๋ถํฐ ์์ํ๊ณ , end-1
๊น์ง ์๋ฆ
๋๋ค. ๊ฐ๊ฒฉ์ ์ค์ ํด์ฃผ์ง ์์ผ๋ฉด 1์
๋๋ค.
๋ค์ mainpage.html ๋ด์ฉ๋ ์์ ํด์ค๋๋ค.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>2021 Dongguk Likelion 3rd session</h1>
<a href="{% url 'first' %}">first</a>
<a href="{% url 'second' %}">second</a>
<img src="{% static 'images/image01.jpg' %}">
<h1>๊ธ ๋ชฉ๋ก</h1>
<div>
{% for blog in blogs %} <!-- blogs์ ๊ฐ์ฒด๋ค์ blog๋ผ๋ ์ด๋ฆ์ผ๋ก ํ๋์ฉ ๊บผ๋ด ๋ฐ๋ณตํ๋ค. -->
<div>
<h3>
{{blog.title}} <br>
{{blog.writer}}<br>
{{blog.summary} <!-- body์์ summary๋ก ๋ณ๊ฒฝ -->
</h3>
</div>
{% endfor %}
</div>
{% endblock %}
๊ฐ์ฒด๋ง๋ค ๋ด์ฉ์ ์ ๋ถ ๋ณผ ์ ์๋ ์์ธ ํ์ด์ง๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. basic/main/views.py
from django.shortcuts import get_object_or_404, render # import get_object_or_404
def detail(request, id):
blog = get_object_or_404(Blog, pk = id) # id์ ํด๋นํ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์๋ค๋ฉด 404 ์๋ฌ
return render(request, 'detail.html', {'blog':blog})
์ด์ ๋ views ์ detail ํจ์๋ฅผ ์์ฑํด๋ณผ๊ฒ์. ๊ธฐ์กด์๋ request๋ง ๋ค์ด์ค๋ฉด ๋ฐ๋ก html ํ์ผ์ ๋๊ฒจ์ฃผ๋ ๋ฐฉ์์ผ๋ก ๊ฐ๋ฅํ์ง๋ง, ์ด๋ฒ์๋ ๋ช ๋ฒ์งธ ๊ฐ์ฒด์ธ์ง๋ ๊ฒฐ์ ํด์ฃผ์ด์ผ ํ๋ฏ๋ก id
๋ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์์ผ ํฉ๋๋ค. ๋ค์์ผ๋ก๋ id
์ ํด๋นํ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์์ผํฉ๋๋ค. ๊ธฐ์กด์ฒ๋ผ objects ๋ก ๊ฐ์ ธ์ค๊ฒ ๋๋ฉด ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผํฉ๋๋ค. ๋ฐ๋ก get_obejct_or_404
์
๋๋ค. ์์์ imort๋ฅผ ๋จผ์ ํด์ฃผ๊ณ , ์ด ๋ฉ์๋๋ ๋ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ๊ฒ ๋๋๋ฐ ์ฒซ๋ฒ์งธ๋ก ์ด๋ค ํด๋์ค์์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ฌ์ง, ๋๋ฒ์งธ๋ก ์์ ํด๋์ค์ ๋ช๋ฒ์งธ ๊ฐ์ฒด์ธ์ง๋ฅผ ๊ฒฐ์ ํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ช ๋ฒ์งธ ๊ฐ์ฒด์ธ์ง๋ pk(primary key) ๋ฅผ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค. pk๋ ๊ฐ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ถํด์ฃผ๋ ํค ๊ฐ์
๋๋ค.
basic/basic/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.showmain, name="showmain"),
path('first/', views.first, name="first"),
path('second/', views.second, name="second"),
path('<str:id>', views.detail, name="detail"),
]
view๋ฅผ ์ ์ํด์คฌ์ผ๋ url์ ํด์ค์ผํฉ๋๋ค. ๊ธฐ์กด์ ๋ฌ๋ผ์ง ์ ์ <str:id>
์
๋๋ค. id
๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง ๊ฐ์ str(๋ฌธ์์ด) ํ์
์ผ๋ก ์ฃผ์๋ก ๋ณด๋ธ๋ค๋ ์๋ฏธ์
๋๋ค. ์ด ๋ถ๋ถ์ ๋ฐ๋ก path converter ๋ผ๊ณ ๋ถ๋ฅด๋๋ฐ ์ด๋ฅผ ํตํด ์ฌ๋ฌ ๊ฐ์ฒด๋ค์ ๋ค๋ฃจ๋ ๊ณ์ธต์ ์ธ url์ ์๋์ผ๋ก ์ฝ๊ณ ํธํ๊ฒ ์์ฑํ ์ ์์ต๋๋ค. ์ฒซ๋ฒ์งธ ๊ธ์ ์์ธ ํ์ด์ง์ ๋๋ฒ์งธ ๊ธ์ ์์ธ ํ์ด์ง url์ ๋ฌ๋ผ์ผ๊ฒ ์ฃ . ๋ํ, ํ๋์ ํ
ํ๋ฆฟ์ผ๋ก ์ฌ๋ฌ ๊ฒฝ์ฐ์ ํ์ด์ง๋ฅผ ๋์ธ ์ ์์ต๋๋ค.
๊ธฐ์กด์ url์ ๊ธฐ๋ณธ์ ์ผ๋ก str ํ์
์ผ๋ก ์ธ์์ ํฉ๋๋ค. id๊ฐ์ ์ ์์ด๋ฏ๋ก <int:id>
๋ก ํด์ฃผ์ด๋ ์ข์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ views.py์์ show ํจ์๋ฅผ ํธ์ถํ ๋ id๊ฐ์ ๋ฐ๋๋ค๊ณ ํ์์ฃ . ์ฌ๊ธฐ์ id๊ฐ ๋ฐ๋ก
์ด urls.py์ id
์
๋๋ค. ๋ค์์ url ๋ก ์ ์์ id
๋ฅผ views ์ detail
ํจ์๋ก ๋๊ฒจ์ฃผ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด detail
ํจ์๋ id
์ ํด๋นํ๋ ๊ฐ์ฒด๋ฅผ blog
๋ผ๋ ๋ณ์์ ๋ด๊ณ , ์๋ค๋ฉด 404์๋ฌ๋ฅผ ๋์ฐ๊ฒ ์ฃ .
๋ง์ฝ <str:blog_id>
์๋ค๋ฉด views.py์๋ def detatil(request,blog_id)
์ฌ์ผ ํฉ๋๋ค.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>2021 Dongguk Likelion 3rd session</h1>
<a href="{% url 'first' %}">first</a>
<a href="{% url 'second' %}">second</a>
<img src="{% static 'images/image01.jpg' %}">
<h1>๊ธ ๋ชฉ๋ก</h1>
<div>
{% for blog in blogs %}
<div>
<h3>
{{blog.title}} <br>
{{blog.writer}}<br>
{{blog.summary}}
<a href="{% url 'detail' blog.id %}">...์์ธํ</a>
</h3>
</div>
{% endfor %}
</div>
{% endblock %}
์์ธ ํ์ด์ง๋ก ์ด๋ํ ์ ์๋ ๋ฒํผ์ ๋งํฌ๋ฅผ ์ฐ๊ฒฐํด์ค๋๋ค. blog.id
๋ฅผ ํตํด id๊ฐ์ URL ๋ค์ ๋ถ์ฌ์ ๋ณด๋ด์ค์ผ ํฉ๋๋ค. ๊ทธ๋์ผ ์๊น ์์ฑํ detail
์ด๋ผ๋ ์ด๋ฆ์ url์์ id
๋ฅผ ๋ฐ์ detail
ํจ์๋ก ๋ณด๋ด์คํ
๊ณ , ๊ทธ๋์ผ deatail
ํจ์๊ฐ id
์ ๋ง๋ ๊ฐ์ฒด๋ฅผ ์ฐพ์ blog
๋ผ๋ ์ด๋ฆ์ ๋ด์ deatil.html
๋ก ๋ณด๋ด์ด ๋์์ค ์ ์๊ฒ ์ฃ .
basic/main/templates/main/detail.html์ ๋ง๋ค์ด์ค๋๋ค. ์์ธ ํ์ด์ง์ template์ด์์.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>
{{blog.titile}}
์์ฑ์: {{blog.writer}}
๋ ์ง: {{blog.pub_date}}
</h1>
<p>{{blog.body}}</p>
{% endblock %}
READ ์๋ฃ!