일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 메서드채이닝
- 깃모지
- class
- Colab
- 구글코랩
- 캐시의 지역성
- nextjs
- 추상 클래스
- 정수
- mnist
- PYTHON
- Next.js
- randrange
- 식별연산자
- 비공개 속성
- 메서드
- 맴버연산자
- 인공신경망
- self
- neural network
- choice
- cache locality
- 정적 메서드
- f-string
- built-in function
- ITER
- Keras
- 실수
- __init__
- gitmoji
- Today
- Total
IT world
[Django] 24.02.26 Django CRUD 실습 본문
오늘은 Create, Read, Update, Delete에 대한 Django 실습을 진행했다.
즉 저장된 내역을 읽고, 새로운 데이터를 추가하고, 기존 데이터를 수정하고, 삭제하는 내용을 실습했다.
이전 내용을 이어서 admin 페이지에서 생성한 블로그 게시물을 사용하여 CRUD 기능을 구현할 것이다.
현재 BLOG > Posts 에는 3개의 게시물이 작성되어 있다.
우선 Models.py에 DB 내용을 가져오고 admin.py에 DB에 반영한 것을 admin 페이지에 반영했다.
(각 .py 역할이 정확한 내용인지 잘 모르겠다. 추후 수정 예정하겠다.)
# blog > models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
contents = models.TextField()
main_image = models.ImageField(upload_to="blog/%Y/%m/%d/", blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
# blog > admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)
여기서 각 페이지를 생성할 때 input 태그, textarea 태그를 사용한 것이 아닌 Model Form을 사용하여 페이지를 구성했다.
Model Form은 자동으로 Form을 생성해주는 기능으로 모델과 필드를 지정하면 모델폼이 자동으로 폼 필드를 생성한다.
즉 모델에 정의된 필드를 바탕으로 form을 자동 생성하고 각 필드 유형에 맞는 폼 필드가 매핑되어 자동으로 생성된다. 또한 제출된 폼 데이터에 대한 유효성 검사를 자동으로 수행한다. Model Form을 사용하면 Form을 위한 HTTML 작성이 필요없고 재사용이 가능하다.
forms.py를 만들고 어떤 필드를 입력받을지 정하고 각 페이지에 form을 반영했다. (각 페이지 form 사용은 아래 예시에서 확인)
- from django import forms: django에서 제공하는 forms 기능을 사용하기 위해 import
- from .models import Post: Post 모델을 사용하기 위해 import
- class PostForm(forms.ModelForm): PostForm이라는 이름의 모델폼 클래스 생성
- model = Post: form에서 사용할 모델이 Post을 명시
- fields: Post 모델에서 입력받고 싶은 필드를 리스트 형태로 작성("__all__" : 모든 필드 사용)
# forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
title = forms.CharField(max_length=10)
contents = forms.CharField(widget=forms.Textarea)
class Meta:
model = Post
fields = ["title", "contents"]
아래 코드는 form 태그를 작성하는 HTML과 forms.py에 출력할 필드를 작성하고 {{form}}에 담아서 호출한 방법 차이입니다.
1. 입력 받을 필드들을 input 태그를 써서 만드는 방법(비추천)
<form method = "POST">
{% csrf_token %}
<input type = "text" name = "title">
<textarea name = "content">
<button type="submit">저장</button>
</form>
2. 저장할 필드를 파이썬 파일에 작성하고 파일을 {{form}}에 담아서 불러오기만 하는 방법
<form method = "POST">
{% csrf_token %}
{{ form }}
<button type="submit">저장</button>
</form>
1. Read
우선 Read 작업, 즉 DB에 저장되어 있는 게시글의 내용을 출력할 것이다.
경로는 blog/, blog/detailNo 로 blog의 메인 페이지에서는 저장된 목록을 보여주며, 목록에 출력된 게시글 클릭 시 세부 페이지로 이동하여 해당 게시글의 정보를 출력할 것이다. 검색 기능을 추가하여 저장된 목록 출력 페이지에 해당 검색내용이 포함된 내용 전부를 출력할 수 있도록 작성하였다.
아래 코드는 blog/로 접속할 경우와 세부 내역으로 접속할 경우 처리 방식을 작성했다.
# blog > urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.blog_list, name="blog_list"),
path("<int:pk>/", views.blog_details, name="blog_details"),
path("create/", views.blog_create, name="blog_create"),
path("update/<int:pk>/", views.blog_update, name="blog_update"),
path("delete/<int:pk>/", views.blog_delete, name="blog_delete"),
]
# blog > views.py
from django.shortcuts import render
from .models import Post
# db 내용 호출
def blog_list(request):
if request.GET.get("q"):
db = Post.objects.filter(
Q(title__contains=request.GET.get("q"))
| Q(contents__contains=request.GET.get("q"))
).distinct()
else:
db = Post.objects.all()
context = {"db": db}
return render(request, "blog/blog_list.html", context)
def blog_details(request, pk):
db = Post.objects.get(pk=pk)
context = {"db": db}
return render(request, "blog/blog_details.html", context)
출력 페이지는 아래와 같이 작성하였고, title에 링크를 설정하여 클릭 시 세부 정보 페이지로 이동하도록 설정했다.
"{% url 'blog_details' post.id %} : blog_details/id값 의 경로"
# blog/blog_list.html
<h1>게시판</h1>
<form action="" method="get">
<input type="text" name="q" type="search">
<button type="submit">검색</button>
</form>
<ul>
{% for post in db %}
<li>
<a href="{% url 'blog_details' post.id %}">{{ post.title }}</a>
<p>{{ post.contents }}</p>
</li>
{% endfor %}
</ul>
# blog/blog_details.html
<h1>게시판</h1>
<p>{{db.title}}</p>
<p>{{db.contents}}</p>
<p>{{db.created_at}}</p>
<p>{{db.updated_at}}</p>
<p>{{db.id}}</p>
{% if db.main_image %}
<img src="{{ db.main_image.url }}" alt="">
{% endif %}
<a href="{% url 'blog_list' %}">뒤로가기</a>
blog 메인 페이지 |
|
세부 페이지 |
검색 시 출력 메인 페이지 |
2. Create
Create 단계에서는 새로운 데이터를 생성하고, 이미지 저장에 대한 기능을 구현했으며, blog/create/ 경로 접속 시 새로운 데이터를 입력할 수 있다.
해당 경로로 접속 했을 때 제목과 내용, 이미지를 입력하고 저장할 수 있게 구현했다. 또한 이미지 저장 기능을 위해서 views.py > blog_create 함수에서 request.FILES 를 추가하였고 blog_create.html 에서 form에 enctype="multipart/form-data" 를 추가해줘야한다.
# blog > views.py
from django.shortcuts import redirect
# ... 생략 ...
def blog_create(request):
if request.method == "GET":
form = PostForm()
context = {"form": form}
return render(request, "blog/blog_create.html", context)
elif request.method == "POST":
form = PostForm(request.POST, request.FILES) # request.FILES 추가
if form.is_valid():
post = form.save()
# detail로 가야한다!
# return redirect('blog_details', pk=post.pk)
return redirect("blog_list")
else:
context = {"form": form}
return render(request, "blog/blog_create.html", context)
# blog > blog_create.html
<form action="{% url 'blog_create'%}" method="post" enctype="multipart/form-data">
{# 해킹 공격 방어를 위한 토큰입니다. #}
{% csrf_token %}
{{ form }}
<button type="submit">저장</button>
</form>
3. Delete
저장된 각 세부 내역 페이지에서 삭제가 가능하도록 기능을 구현했고, 해당 페이지의 id값을 확인하고 DB에 해당 pk 값의 내용을 삭제했다.
# blog > views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.db.models import Q
from .models import Post
from .forms import PostForm
# ... 생략 ...
def blog_delete(request, pk):
# post = Post.objects.get(pk=pk)
post = get_object_or_404(Post, pk=pk)
print(post)
if request.method == "POST":
post.delete()
return redirect("blog_list")
# blog > blog_details.html
# 삭제하기 버튼 추가
# ..... 생략 ......
<!-- 삭제하기 버튼 -->
<form action="{% url 'blog_delete' db.id %}" method="post"> <!-- blog_delete/id -->
{% csrf_token %}
<button type="submit">삭제하기</button>
</form>
4. Update
저장된 각 세부 내역 페이지에서 수정하기가 가능하도록 기능을 구현했다.
# blog > views.py
def blog_update(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, request.FILES, instance=post)
if form.is_valid():
form.save()
return redirect("blog_details", pk=post.pk)
else: # request method가 Get일 경우
form = PostForm(instance=post)
context = {"form": form, "pk": pk}
return render(request, "blog/blog_update.html", context)
# blog > blog_details.html
# 수정하기 버튼 추가
# ..... 생략 ......
<!-- 수정하기 버튼 -->
<a href="{% url 'blog_update' db.id %}">수정하기</a>
세부 내역 페이지(수정하기) |
|
수정 내용 작성 페이지 |
수정 내용 반영 확인 |
'모두의 연구소(오름캠프) > AI 모델 활용 백엔드 개발 과정' 카테고리의 다른 글
[Django] 24.02.27 Django CBV 실습 (1) | 2024.02.27 |
---|---|
[Django] 24.02.23 Django 실습2 (0) | 2024.02.23 |
[Django] 24.02.21 Django 실습 (0) | 2024.02.21 |
[Django] 24.02.20 Django에 대해서 (0) | 2024.02.20 |
[FrontEnd] 24.02.19 Bootstrap 과 Tailwind (0) | 2024.02.19 |