Notice
Recent Posts
Recent Comments
Link
오늘도 개발
Django 인트로 본문
0. Django란?
- 동적인 웹페이지를 만들 수 있게 해주는 python의 프레임워크
1. Django 설치
- python 설치되어있는지 확인
- pip 설치되어있는지 확인
- django 설치하기(“pip3 install Django”)
2. Django에서 프로젝트 시작하기
- 스타터 파일 생성하기 (“django-admin startproject PROJECT_NAME”) -> 프로젝트명에 - 사용 불가
- 스타터 파일로 이동 (“cd PROJECT_NAME”)
- 개발용 로컬 서버 열어보기 (“python3 manage.py runserver”)
3. 프로젝트에 앱 생성하기
- 한 웹사이트는 다양한 역할을 하는 앱으로 구성됨 (예: 구글 - 구글 캘린더, 이미지…)
- 앱 폴더 생성하기 (“python3 manage.py startapp hello”)
4. 프로젝트에 앱 추가하기
1) “settings.py”파일의 INSTALLED_APPS 리스트에 앱 추가하기

INSTALLED_APPS = [
'hello',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
2) 앱 폴더 속 view.py 파일에 view 추가하기
- view.py는 여러 개의 view로 이루어짐
- 하나의 view는 유저가 보는 하나의 페이지
from django.shortcuts import render
from django.http import HttpResponse
# 첫번째 view
def index(request):
return HttpResponse("Index of hello app")
3) view에 접근할 수 있는 경로 만들기
- 앱 폴더 속 “views.py”와 같은 위치에 “urls.py” 파일 만들기
- “urls.py”에 “urlpatterns” 리스트 만들고 views.py에 있는 각 view의 경로 작성하기
# urls.py 파일
from django.urls import path
from . import views
# 프로젝트 url/hello/에 유저가 접속하면 "views.py"의 index 함수를 실행하라는 뜻
urlpatterns = [
# 경로, view에서 내보낸 함수, alias 순
path("", views.index, name="index")
]
4) local “urls.py” 파일을 global “urls.py” 파일과 연결하기
- include 모듈 import하기
- hello 앱의 “urls.py”에 있는 모든 url을 global “urls.py”의 urlpatterns 리스트에 추가하기 (include 사용)
- 이제 URL 끝에 /hello 붙이면 hello 앱 내 view를 볼 수 있음
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include("hello.urls"))
]
5. “localhost:8000/hello/”에 접속하면 일어나는 일
- Django가 base URL 다음에 오는 hello 발견
- global의 “urls.py”에서 hello와 매치하는 url pattern 서치->발견
- url pattern이 local의 “urls.py”를 include한 것을 발견
- local의 “urls.py”에서 매치하는 url pattern 서치->발견
- “views.py”에서 index 함수 서치/실행
6. Django Templates로 쉽게 webpage 만들기
- 앱 내 “templates” 폴더 만들기
- “templates” 폴더 안에 앱 이름과 같은 폴더 만들기
- 앱 이름과 같은 폴더 안에 “index.html” 파일 생성하기
- index.html에 원하는 내용 작성하기
- views.py에 index.html파일 렌더링해서 리턴하는 함수 만들기
# views.py
# render의 세번째 argument는 context라고 부름
# context는 python dictionary 형태로 작성
# html에서 context의 key로 value에 접근가능
from django.shortcuts import render
from django.http import HttpResponse
def greet(request, name):
return render(request, "hello/greet.html", {
"name": name.capitalize()
})
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello, !</h1>
</body>
</html>
cf) template inheritance : 공통적으로 사용하는 코드 한 번만 작성한 후 원하는 html 파일마다 상속
- “templates” 폴더 안에 “layout.html”파일 생성
<!DOCTYPE html>
<html lang="en">
<head>
<title>Tasks</title>
</head>
<body>
({와 %로 표시) block body
({와 %로 표시) endblock
</body>
</html>
- “templates” 폴더 안에 원하는 파일(ex: index.html)생성 후 layout.html 파일 연결, 필요한 부분만 작성하면 끝
({와 %로 표시) extends "tasks/layout.html"
({와 %로 표시) block body
<h1>Tasks:</h1>
<ul>
({와 %로 표시) for task in tasks
<li></li>
({와 %로 표시) endfor
</ul>
({와 %로 표시) endblock
6. CSS파일로 스타일링하기
- 앱 내 static 폴더 만들기
- static 폴더 내 앱 이름으로 폴더 만들기
- 폴더 내 css파일 만들기
- html 파일에 동적 주소 링크하기
({와 %로 표시) load static
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="({와 %로 표시) static 'newyear/styles.css'">
<title>Hello</title>
</head>
<body>
<h1>Hello, !</h1>
</body>
</html>
7. html파일에 a태그로 링크 만들어서 앱 끼리 연결하기
# urls.py 파일
from django.urls import path
from . import views
# django가 url의 name을 보고 렌더링 할 때, 다른 앱의 이름이 같은 url과 구분할 수 변수 만들어줌
app_name = "tasks"
urlpatterns = [
path("", views.index, name="index")
]
<!-- urls.py파일에서 링크할 url에 부여한 name 사용 -->
<!-- urls.py파일에서 app_name으로 지정한 것도 써주면 더 정확 -->
<a href="({와 %로 표시)url 'tasks:index'(%와 }로 표시)">back to index</a>
8. CSRF token
- CSRF : Cross-site Request Forgery의 약자
- CSRF attack : 악성 유저가 엉뚱한 사이트에서 내 서버로 request를 보내는 것
- CSRF token : django가 response로 템플릿을 렌더링할 때 각 세션마다 생성하는 고유한 암호.
- 작동 방식 : 클라이언트가 form이 있는 템플릿 렌더링 request -> django 서버가 템플릿 렌더링해서 response, 고유한 암호 발행 -> 클라이언트가 form을 제출하는 request 보냄 -> django 서버가 아까 생성한 암호와 일치하는 암호를 가진 클라이언트에서 온 건지 체크 -> 일치 시 통과/불일치 시 접근 거부
- 사용 : html파일의 form 태그 안에 “csrf_token” 작성
<form action="" method="post">
({와 %로 표시) csrf_token
<input type="text" name="task">
</form>
9. Django Forms
- html 작성할 필요 없이 django로 form 만들 수 있음
- 자동으로 django가 client-side validation 실행 : 유저가 알맞은 답을 적지 않으면 서버로 제출할 수 없게 클라이언트에서 막아주는 장치가 있다는 뜻
- 그렇더라도 server-side validation 필요 : client-side validation는 무력화하기 쉽고, 유저가 업데이트 안 된 웹페이지로 보고 있으면 validation 안될 수도 있음
- django forms 사용하면 client-side validation, server-side validation 둘 다 하기 쉬움
cf) Django Form으로 제출 시 일어나는 일
- 서버가 request를 받음 : request는 <WSGIRequest: POST ‘/tasks/add’> 형태로 받음
- form으로 제출된 내용은 request.POST에 딕셔너리 형태로 저장됨 : request.POST의 내용 <QueryDict: {‘csrfmiddlewaretoken’: [‘9G5…’], ‘task’: [‘do the dishes’], ‘priority’: [‘1’]}>
- 제출된 내용(request.POST)를 form의 형태로 저장할 수 있음 : NewTaskForm(request.POST)입력하면 <tr><th><label for="id_task">New Task:</label></th><td><input type="text" name="task" value="do the dishes" required id="id_task"></td></tr> 형태로 저장
- 내장된 form 모듈의 method인 “is_valid”로 form validation할 수 있음
- “is_valid”로 validation하면, “cleaned_data”라는 딕셔너리 생성됨
- cleaned_date[‘field_name’]로 접근 가능. self.field_name로도 접근 가능하지만 안전하지 않음(왜?)
# views.py
# 필요한모듈 import해야 함
from django.shortcuts import render
from django import forms
from django.urls import reverse
from django.http import HttpResponseRedirect
tasks = ["one", "two", "three"]
# forms 모듈에서 Form 클래스 상속시킴
class NewTaskForm(forms.Form):
task = forms.CharField(label="New Task")
def add(request):
if request.method == "POST":
form = NewTaskForm(request.POST)
if form.is_valid():
task = form.cleaned_data["task"]
tasks.append(task)
return HttpResponseRedirect(reverse("tasks:index"))
return render(request, "tasks/add.html", {
"form": NewTaskForm()
})
<form action="({와 %로 표시) url 'tasks:add'%와 }로 표시)" method="post">
</form>
10. Django Sessions
- session : 웹사이트 방문자 각각의 고유한 데이터를 서버에 저장하는 방식
- django는 디폴트로 데이터를 table에 저장 -> session에 관한 데이터도 table에 저장
- table을 미리 만들지 않고 서버 가동하면 table이 없다는 오류 뜸
- terminal에서 python manage.py migrate 실행하면 django 데이터베이스 내 디폴트 테이블 생성할 수 있음
- session의 데이터는 dictionary 형태로 저장됨
def index(request):
# session에 tasks라는 key가 없으면 만들고 빈 리스트를 value로 할당하라는 뜻
if "tasks" not in request.session:
request.session["tasks"] = []
return render(request, "todo/index.html", {
"tasks": request.session["tasks"]
})
참조
CS50’s Web Programming with Python and JavaScript - Week3. Django
CS50's Web Programming with Python and JavaScript
This course picks up where Harvard University's CS50 leaves off, diving more deeply into the design and implementation of web apps with Python, JavaScript, and SQL using frameworks like Django, React, and Bootstrap. Topics include database design, scalabil
cs50.harvard.edu
'웹 프로그래밍 > Django' 카테고리의 다른 글
| ManyToManyField VS ForeignKey (0) | 2022.07.05 |
|---|---|
| Django와 데이터베이스 - 2) 마이그레이션(migration) (0) | 2022.07.01 |
| Django와 데이터베이스 - 1) Django 모델(Model) (0) | 2022.06.30 |
| Django와 데이터베이스 - 0) Django ORM (0) | 2022.06.29 |
| Django 개요 - 기본 개념, 프로젝트 세팅 (0) | 2022.06.28 |