본문 바로가기
Study/Django

[Django] Django로 CRUD를 구현해보자

by ngool 2024. 9. 28.

C.R.U.DCreate, Read, Update, Delete를 의미하는 약어입니다.

 

이번 포스트에서는 Django로 CRUD를 구현하는 과정을 A-Z까지 정리해보겠습니다!


초기 환경 설정

1. 가상 환경 설치

$ python -m venv venv
$ source venv/Scripts/activate

 

2. django 설치

$ pip install django

# 패키지 설치 후 requirements.txt에 기록
$ pip freeze > requirements.txt

 

3. crud 프로젝트 생성

$ django-admin startproject crud .

 

4. article 앱 생성 및 등록

$ python manage.py startapp articles
  • settings.pyINSTALLED_APPS에 등록
# crud/settings.py

INSTALLED_APPS = [
    'articles',        # <---------------

    'django.contrib.admin',
    # . . .
]

BASE_DIR / templates 폴더 생성

1. 최상단 templates 폴더에 base.html 파일 생성

$ mkdir templates
$ touch templates/base.html

 

2. base.htmlblock 태그 추가

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
  <!-- block 태그 추가 -->
  {% block content %}
  {% endblock content %}
</body>
</html>

 

3. settings.pytemplates 폴더 등록하기

# settings.py

TEMPLATES = [
    {
        # . . .
        'DIRS': [
            BASE_DIR / 'templates',
         ]
    },
]

Article 모델 클래스 작성하기

1. Article 클래스 정의

# aritlces/models.py

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=10)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

 

2. 모델 클래스 DB에 반영하기

$ python manage.py makemigrations
$ python manage.py migrate

 

3. Admin 계정 생성, Admin 사이트에서 레코드 생성하기

$ python manage.py createsuperuser
Username (leave blank to use 'ssafy'): admin
Email address: 
Password: 
Password (again): 
This password is too short. It must contain at least 8 characters.
This password is too common.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully

=> 이후 서버 실행해서 admin 사이트 접속 후 로그인 가능

 

3. Article을 Admin 사이트에 등록하기

# articles/admin.py

from django.contrib import admin
from .models import Article

admin.site.register(Article)

=> admin 사이트에 Article 테이블이 보이게 됨


/articles/ 로 시작하는 url 처리

1. settings.py 수정

# crud/urls.py
from django.urls import path, include               # <------------

urlpatterns = [
    path('admin/', admin.site.urls),

    path('articles/', include('articles.urls')),    # <------------
]

 

2. articles 폴더에 urls.py 생성

# articles/urls.py
from django.urls import path
from . import views

app_name = 'articles'
urlpatterns = [

]

=> app_name이 누락되면 에러가 발생합니다!!


ArticleForm 클래스 정의

1. articles/forms.py 생성

$ mkdir articles/forms.py

 

2. ArticleForm 클래스 정의

# articles/forms.py
from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'

전체 게시글 조회

1. url 등록

# urls.py
urlpatterns = [
    path('', views.index, name='index'),  # <-----------------
]

 

2. view 함수 작성

# views.py

def index(request):
    articles = Article.objects.all()
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index.html', context)

 

3. index.html 작성

# articles/templates/articles/index.html

{% extends "base.html" %}

{% block content %}
<h1>INDEX</h1>

{% for article in articles %}
<p>글 번호: {{ article.pk }}</p>
<p>글 제목: {{ article.title }}</p>
<hr>
{% empty %}
<p>아직 작성된 게시글이 없습니다.</p>
{% endfor %}

{% endblock content %}

상세 게시글 조회

1. url 등록

# urls.py
urlpatterns = [
    path('<int:article_pk>/', views.detail, name='detail'),  # <-----------------
]

 

2. view 함수 작성

# views.py

def detail(request, article_pk):
    article = Article.objects.get(pk=article_pk)
    context = {
        'article': article,
    }
    return render(request, 'articles/detail.html', context)

 

3. detail.html 작성

# articles/templates/articles/detail.html

{% extends "base.html" %}

{% block content %}
<h1>DETAIL</h1>

<p>글 번호: {{ article.pk }}</p>
<p>글 제목: {{ article.title }}</p>
<p>글 내용: {{ article.content }}</p>
<p>작성 시각: {{ article.created_at }}</p>
<p>수정 시각: {{ article.updated_at }}</p>
<hr>
<a href="{% url "articles:index" %}">[INDEX]</a>
{% endblock content %}

 

4. 게시글 전체 조회 페이지에서 상세보기 링크 추가

# articles/templates/articles/index.html

<p>글 번호: {{ article.pk }}</p>
<p>글 제목: {{ article.title }}</p>

<a href="{% url "articles:detail" article.pk %}">[상세보기]</a>

<hr>

 


게시글 생성

1. url 등록

# urls.py
urlpatterns = [
    # ... 
    # 게시글 생성 => /artices/create/    
    path('create/', views.create, name='create'), # <-----
]

 

2. view 함수 작성

# views.py

from django.shortcuts import render, redirect  # <--- redirect 추가

def create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save()
            return redirect('articles:detail', article.pk)
    else:
        form = ArticleForm()
    context = {
        'form': form,
    }
    return render(request, 'articles/create.html', context)

 

3. create.html 작성

# articles/templates/articles/create.html

{% extends "base.html" %}

{% block content %}
<h1>CREATE</h1>

<form action="{% url "articles:create" %}" method='POST'>
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="제출">
</form>
{% endblock content %}

=> csrf_token 잊지 말기!!

 

4. index.html에 [CREATE] 링크 걸기

# articles/templates/articles/index.html

{% extends "base.html" %}

{% block content %}
<h1>INDEX</h1>
<a href="{% url "articles:create" %}">[CREATE]</a>
. . .
{% endblock content %}

게시글 삭제

1. url 등록

# urls.py
urlpatterns = [
    # ... 
    # 게시글 삭제 => /artices/1/delete/
    path('<int:article_pk>/delete/', views.delete, name='delete'), # <-----
]

 

2. view 함수 작성

# views.py
def delete(reqeust, article_pk):
    article = Article.objects.get(pk=article_pk)
    article.delete()
    return redirect('articles:index')

 

3. detail.html에 [DELETE] 버튼 추가

# articles/templates/articles/detail.html

{% extends "base.html" %}
<h1>DETAIL</h1>

. . .

<form action="{% url "articles:delete" article.pk %}" method="POST">
  {% csrf_token %}
  <input type="submit" value="[DELETE]">
</form>

<a href="{% url "articles:index" %}">[INDEX]</a>
{% endblock content %}

게시글 수정

1. url 등록

# urls.py
urlpatterns = [
    # ... 
    # 게시글 수정 => /artices/1/update/    
    path('<int:article_pk>/update/', views.update, name='update'), # <-----
]

 

2. view 함수 작성

# views.py

def update(request, article_pk):
    article = Article.objects.get(pk=article_pk)
    if request.method == 'POST':
        form = ArticleForm(request.POST, instance=article)
        if form.is_valid():
            form.save()
            return redirect('articles:detail', article_pk)
    else:
        form = ArticleForm(instance=article)
    context = {
    	'article': article,
        'form': form,
    }
    return render(request, 'articles/update.html', context)

 

3. update.html 작성

# articles/templates/articles/update.html

{% extends "base.html" %}

{% block content %}
<h1>UPDATE</h1>

<form action="{% url "articles:update" article.pk %}" method='POST'>
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="제출">
</form>
{% endblock content %}

 

4. detail.html에 [UPDATE] 링크 추가

# articles/templates/articles/detail.html

{% extends "base.html" %}

{% block content %}
. . .

<a href="{% url "articles:update" article.pk %}">[UPDATE]</a>

. . .
{% endblock content %}