- 가상 환경 및 Python 개발 환경 설정
$ python -m venv venv
$ source venv/Scripts/activate
$ pip install django==3.2.18
$ django-admin startproject pjt
$ cd pjt
$ python (manage.py)(<http://manage.py/>) startapp app
- settings.pyINSTALLED_APPS에 앱 추가
- pjt 폴더에 템플릿 폴더 생성(base.html 저장)
Bootstrap CDN을 가져온 후 본문에 차단 태그를 붙여 넣습니다.
{% block content %}
{% endblock content %}
- settings.pybase.html 호출 경로 설정
TEMPLATES = (
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': (BASE_DIR / 'templates'),
'APP_DIRS': True,
'OPTIONS': {
'context_processors': (
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
),
},
},
)
- app 폴더에 templates\app\ 하위 폴더를 만듭니다(HTML 템플릿 저장).
Index.html 만들기
확장 태그로 base.html 호출, 블록 태그 삽입
{% extends 'base.html' %}
{% block content %}
<h1>INDEX</h1>
{% endblock content %}
- 앱 URL 매핑
urls.py를 각 앱에 매핑
include(): 다른 urlconf를 참조할 수 있도록 도와주는 기능
URL 태그로 쉽게 참조할 수 있도록 경로 함수에 이름을 인수로 포함합니다.
from django.contrib import admin
from django.urls import path, include
urlpatterns = (
path('admin/', admin.site.urls),
path('app/', include('app.urls'), name="app"),
)
- 앱 폴더에서 urls.py 생산하는
다른 앱이 동일한 URL을 사용하는 경우 app_name 생성
from django.urls import path
from . import views
app_name="app"
urlpatterns = (
path('index/', views.index, name="index"),
)
- views.index 정의
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'app/index.html')
- models.py에서 모델 생성
→ DB 스키마 정의
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=10)
content = models.TextField()
created_at = models.DateTimeField()
updated_at = models.DateTimeField()
- 정의된 스키마를 실제 데이터베이스에 반영하도록 마이그레이션
$ python manage.py makemigrations
$ python manage.py migrate
- QuerySet API를 사용한 CRUD
django는 Python을 통해 데이터를 조작하는 ORM을 제공합니다.
- 만들다
article = Article() # 클래스를 통한 인스턴스 생성
article.title=""
article.content="" # 인스턴스 변수 생성 후 값 할당
article.save() # save메서드 호출하여 저장
article = Article(title="", content="")
article.save()
Article.objects.create(title="", content="")
- 읽다
Article.objects.all()
Article.objects.get(pk=1)
Article.objects.filter(title="ssafy")
Article.objects.filter(content__contains=='ss')
- 업데이트하려면
article = Article.objects.get(pk=1) # 인스턴스 호출
article.title="update" # 인스턴스 변수 변경
article.save() # 저장
- 끄다
article = Article.objects.get(pk=1) # 인스턴스 호출
article.detete() # 삭제
- views.py에서 인덱스 함수를 정의합니다.
from django.shortcuts import render
from .models import Article
# Create your views here.
def index(request):
articles = Article.objects.all()
context = {
'articles': articles
}
return render(request, 'app/index.html', context)
- index.html 페이지 설정
{% extends 'base.html' %}
{% block content %}
<h1>INDEX</h1>
<hr>
{% for article in articles %}
<p>글 번호: {{ article.pk }}</p>
<p>글 제목: {{ article.title }}</p>
<p>글 내용: {{ article.content }}</p>
<hr>
{% endfor %}
{% endblock content %}
- url.py상세 페이지 URL 설정
from django.urls import path
from . import views
app_name="app"
urlpatterns = (
path('index/', views.index, name="index"),
path('<int:pk>/', views.detail, name="detail"),
)
- views.py에서 세부 기능 정의
def detail(request, pk):
article = Article.objects.get(pk=pk)
context = {
'app': article
}
return render(request, 'app/detail.html', context)
- detail.html 작성
{% extends 'base.html' %}
{% block content %}
<h1>DETAIL</h1>
<h3> {{ article.pk }} 번째 글</h3>
<hr>
<p>제목: {{ app.title }}</p>
<p>내용: {{ app.content }}</p>
<p>작성: {{ app.created_at }}</p>
<p>수정: {{ app.updated_at }}</p>
<hr>
<a href="http://stubborngastropod.m/{% url"app:index' %}">뒤로 가기</a>
{% endblock content %}
- index.html의 게시물을 클릭할 수 있도록 태그 추가
{% extends 'base.html' %}
{% block content %}
<h1>INDEX</h1>
<hr>
{% for article in app %}
<p>글 번호: {{ article.pk }}</p>
<a href="http://stubborngastropod.m/{% url"app:detail' article.pk %}">
<p>글 제목: {{ article.title }}</p>
</a>
<p>글 내용: {{ article.content }}</p>
<hr>
{% endfor %}
{% endblock content %}
- new.html 만들기
path('new/', views.new, name="new")
def new(request):
return render(request, 'app/new.html')
{% extends 'base.html' %}
{% block content %}
<h1>NEW</h1>
<form action="app:create" method='GET'>
<label for="title">제목:</label>
<input type="text" name="title"><br>
<label for="content">내용:</label>
<textarea type="text" name="content"></textarea><br>
<input type="submit">
</form>
<hr>
<a href="http://stubborngastropod.m/{% url"app:index' %}">뒤로가기</a>
{% endblock content %}
- new.html로 이동할 수 있는 태그
<a href="http://stubborngastropod.m/{% url"app:new' %}">새 글 작성</a>
- 만들다
path('create/', views.create, name="create"),
from django.shortcuts import render, redirect
def create(request):
title = request.GET.get('title')
content = request.GET.get('content')
article = Article(title=title, content=content)
article.save()
return redirect('app:detail', article.pk)
- POST 방식 및 csrf
new.html에서 양식 방법을 POST로 변경(csrf 토큰 사용)
{% extends 'base.html' %}
{% block content %}
<h1>NEW</h1>
<form action="http://stubborngastropod.m/{% url"app:create' %}" method='POST'>
{% csrf_token %}
<label for="title">제목:</label>
<input type="text" name="title"><br>
<label for="content">내용:</label>
<textarea type="text" name="content"></textarea><br>
<input type="submit">
</form>
<hr>
<a href="http://stubborngastropod.m/{% url"app:index' %}">뒤로가기</a>
{% endblock content %}
create 함수에서 요청을 받는 메서드 변경
def create(request):
title = request.POST.get('title')
content = request.POST.get('content')
article = Article(title=title, content=content)
article.save()
return redirect('app:detail', article.pk)
- 끄다
url, 보기 설정, POST 메서드를 사용하여 detail.html에 양식 태그 작성
path('<int:pk>/delete/', views.delete, name="delete"),
def delete(request, pk):
article = Article.objects.get(pk=pk)
article.delete()
return redirect('app:index')
{% extends 'base.html' %}
{% block content %}
<h1>DETAIL</h1>
<h3> {{ app.pk }} 번째 글</h3>
<hr>
<p>제목: {{ app.title }}</p>
<p>내용: {{ app.content }}</p>
<p>작성: {{ app.created_at }}</p>
<p>수정: {{ app.updated_at }}</p>
<hr>
<form action="http://stubborngastropod.m/{% url"app:delete' app.pk %}" method='POST'>
{% csrf_token %}
<input type="submit" value="삭제">
</form>
<a href="http://stubborngastropod.m/{% url"app:index' %}">뒤로 가기</a>
{% endblock content %}
- 업데이트하려면
path('<int:pk>/edit/', views.edit, name="edit"),
def edit(request, pk):
article = Article.objects.get(pk=pk)
context = {
'article': article,
}
return render(request, 'app/edit.html', context)
edit.html
{% extends 'base.html' %}
{% block content %}
<h1>EDIT</h1>
<form action="#" method='POST'>
{% csrf_token %}
<label for="title">제목:</label>
<input type="text" name="title" value="{{article.title}}"><br>
<label for="content">내용:</label>
<textarea type="text" name="content">{{article.content}}</textarea><br>
<input type="submit">
</form>
<hr>
<a href="http://stubborngastropod.m/{% url"app:index' %}">뒤로가기</a>
{% endblock content %}
편집 페이지로 이동하기 위해 detail.html에 태그를 생성합니다.
<a href="http://stubborngastropod.m/{% url"app:edit' app.pk %}">수정</a>
업데이트 로직 생성
path('<int:pk>/update/', views.update, name="update"),
def update(request, pk):
article = Article.objects.get(pk=pk)
article.title = request.POST.get('title')
article.content = request.POST.get('content')
article.save()
return redirect('app:detail', article.pk)
{% extends 'base.html' %}
{% block content %}
<h1>EDIT</h1>
<form action="http://stubborngastropod.m/{% url"app:update' article.pk %}" method='POST'>
{% csrf_token %}
<label for="title">제목:</label>
<input type="text" name="title" value="{{article.title}}"><br>
<label for="content">내용:</label>
<textarea type="text" name="content">{{article.content}}</textarea><br>
<input type="submit">
</form>
<hr>
<a href="http://stubborngastropod.m/{% url"app:index' %}">뒤로가기</a>
{% endblock content %}