[Django] CRUD 알아보기
🏷 Django 파일 살펴보기
-
manage.py
- 장고 앱을 관리하기 위한 각종 명령어를 내장하고 있는 스크립트 파일
- 이 파일을 실행함으로써 장고가 제공하는 각종 명령어 실행 가능
- 장고 앱을 관리하기 위한 각종 명령어를 내장하고 있는 스크립트 파일
-
firstdjango
(프로젝트 폴더)settings.py
: 프로젝트 전반에 걸친 각종 설정을 위한 파일
urls.py
: 이 프로젝트를 실행시킬 때 어떤 웹 앱의 페이지를 어떤 주소에 연결 시킬지 정의하는 파일
wsgi.py
: 웹 사이트 실행 프로세스와 관견하여 사용되는 파일
-
p1
(웹 앱 폴더)admin.py
: 장과 관리자 웹 구성을 위한 파일
apps.py
: 장고 웹 앱에 대한 설정을 위한 파일
models.py
: db에 정의하기 위한 모델들을 정의해두는 코드를 위한 파일
views.py
: 웹 페이지나 웹 요청등을 처리하는 코드를 작성하는 파일
🏷 CRUD 실습
CRUD
➡️ 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능
➡️ Create(생성), Read(읽기), Update(갱신), Delete(삭제)
음식점 리뷰 사이트를 만들어 보자!
1️⃣ Create(생성)
def create(request):
if request.method == 'POST':
form = RestaurantForm(request.POST)
if form.is_valid():
new_item = form.save()
return HttpResponseRedirect('/p1/list/')
form = RestaurantForm()
return render(request, 'p1/create.html', {'form': form})
-
form
: 데이터 유효성 검사에 용이하다.
2️⃣ Read(읽기)
def list(request):
restaurants = Restaurant.objects.all()\
.annotate(reviews_count=Count('review'))\
.annotate(average_point=Avg('review__point'))
paginator = Paginator(restaurants, 5)
page = request.GET.get('page')
items = paginator.get_page(page)
context = {
'restaurants': items
}
return render(request, 'p1/list.html', context)
.
.
.
def detail(request, id):
if id is not None:
item = get_object_or_404(Restaurant, pk=id)
reviews = Review.objects.filter(restaurant=item).all()
return render(request, 'p1/detail.html', {'item': item, 'reviews': reviews})
return HttpResponseRedirect('/p1/list/')
get_object_or_404
:Django
모델을 첫 번째 인자로 받고, 몇 개의 키워드 인수를 모델 관리자인get()
함수로 넘긴다. 만약 존재하지 않을 경우HTTP404
예외가 발생한다.
1️⃣ Update(수정/갱신)
def update(request):
if request.method == 'POST' and 'id' in request.POST:
item = get_object_or_404(Restaurant, pk=request.POST.get('id'))
password = request.POST.get('password', '')
form = UpdateRestaurantForm(request.POST, instance=item)
if form.is_valid() and password == item.password:
item = form.save()
elif request.method == 'GET':
item = get_object_or_404(Restaurant, pk=request.GET.get('id'))
form = RestaurantForm(instance=item)
return render(request, 'p1/update.html', {'form': form})
return HttpResponseRedirect('/p1/list/')
-
요청이
POST
일때와GET
일때를 구분해야 한다.
1️⃣ Delete(삭제)
def delete(request, id):
item = get_object_or_404(Restaurant, pk=id)
if request.method == 'POST' and 'password' in request.POST:
if item.password == request.POST.get('password') or item.password is None:
item.delete()
return redirect('list')
return redirect('restaurant-detail', id=id)
return render(request, 'p1/delete.html', {'item': item})
📌 전체코드
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'p1',
]
urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('p1/', include('p1.urls')),
path('admin/', admin.site.urls),
]
p1/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('list/', views.list, name='list'),
path('create/', views.create, name='restaurant-create'),
path('update/', views.update, name='restaurant-update'),
# path('detail/', views.detail, name='restaurant-detail'),
path('restaurant/<int:id>/delete', views.delete, name='restaurant-delete'),
path('restaurant/<int:id>/', views.detail, name='restaurant-detail'),
path('restaurant/<int:restaurant_id>/review/create/', views.review_create, name='review-create'),
path('restaurant/<int:restaurant_id>/review/delete/<int:review_id>', views.review_delete, name='review-delete'),
path('review/list/', views.review_list, name='review-list'),
]
p1/models.py
from django.db import models
class Restaurant(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=200)
# 왜 charfield를 썼냐면 여기에 이미지의 url을 넣을거기 때문에 실제로는 문자열로 취급 됨
image = models.CharField(max_length=500, default=None, null=True)
# 디폴트 속성을 어떠한 값 이라도 넣어줘야 함
# 우리가 이미 디폴트 속성을 None 이라고 선언해놨으므로 null값을 허용한다는 선언을 해줘야 함
password = models.CharField(max_length=20, default=None, null=True)
# auto_now_add : 최초 저장시에만 현재 날짜로 적용
created_at = models.DateTimeField(auto_now_add=True)
# auto_now : 수정이 될 때 마다 현재 날짜로 적용
updated_at = models.DateTimeField(auto_now=True)
class Review(models.Model):
point = models.IntegerField()
comment = models.CharField(max_length=500)
# on_delete=models.CASCADE : FK를 포함하는 모든 모델 인스턴스도 같이 삭제
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
p1/forms.py
from django.forms import ModelForm
from django import forms
from p1.models import Restaurant, Review
from django.utils.translation import gettext_lazy as _
# 리뷰 선택지 정의
REVIEW_POINT_CHOICES = (
('1', 1),
('2', 2),
('3', 3),
('4', 4),
('5', 5),
)
class ReviewForm(ModelForm):
class Meta:
model = Review
fields = ['point', 'comment', 'restaurant']
labels = {
'point': _('평점'),
'comment': _('코멘트'),
}
widgets = {
# 리뷰를 달 식당 정보가 사용자에게는 보이면 안됨
'restaurant': forms.HiddenInput(),
# 선택지를 인자로 전달
'point': forms.Select(choices=REVIEW_POINT_CHOICES)
}
help_texts = {
'point': _('평점을 입력해주세요.'),
'comment': _('코멘트를 입력해주세요.'),
}
class RestaurantForm(ModelForm):
class Meta:
model = Restaurant
# 입력받을 필드를 정의
fields = ['name', 'address', 'image', 'password']
labels = {
'name': _('이름'),
'address': _('주소'),
'image': _('이미지 url'),
'password': _('게시물 비밀번호'),
}
help_texts = {
'name': _('이름을 입력해주세요.'),
'address': _('주소를 입력해주세요.'),
'image': _('이미지의 url을 입력해주세요.'),
'password': _('비밀번호를 입력해주세요.'),
}
widgets = {
# 사용자 입력 필드에서 비밀번호 입력하는 필드처럼 글자가 가려지는 필드가 나옴
'password': forms.PasswordInput()
}
error_messages = {
'name': {
'max_length': _("이름이 너무 깁니다. 30자 이하로 해주세요."),
},
'image': {
'max_length': _("이미지 주소의 길이 너무 깁니다. 400자 이하로 해주세요."),
},
'password': {
'max_length': _("비밀번호가 너무 깁니다. 20자 이하로 해주세요."),
},
}
class UpdateRestaurantForm(RestaurantForm):
class Meta:
model = Restaurant
exclude = ['password']
p1/views.py
from django.shortcuts import render, get_object_or_404, redirect
from p1.models import Restaurant, Review
from django.core.paginator import Paginator
from p1.forms import RestaurantForm, ReviewForm, UpdateRestaurantForm
from django.http import HttpResponseRedirect
from django.db.models import Count, Avg
def list(request):
restaurants = Restaurant.objects.all()\
.annotate(reviews_count=Count('review'))\
.annotate(average_point=Avg('review__point'))
paginator = Paginator(restaurants, 5)
page = request.GET.get('page')
items = paginator.get_page(page)
context = {
'restaurants': items
}
return render(request, 'p1/list.html', context)
def create(request):
if request.method == 'POST':
form = RestaurantForm(request.POST)
if form.is_valid():
new_item = form.save()
return HttpResponseRedirect('/p1/list/')
form = RestaurantForm()
return render(request, 'p1/create.html', {'form': form})
def update(request):
if request.method == 'POST' and 'id' in request.POST:
item = get_object_or_404(Restaurant, pk=request.POST.get('id'))
password = request.POST.get('password', '')
form = UpdateRestaurantForm(request.POST, instance=item)
if form.is_valid() and password == item.password:
item = form.save()
elif request.method == 'GET':
item = get_object_or_404(Restaurant, pk=request.GET.get('id'))
form = RestaurantForm(instance=item)
return render(request, 'p1/update.html', {'form': form})
return HttpResponseRedirect('/p1/list/')
def detail(request, id):
if id is not None:
item = get_object_or_404(Restaurant, pk=id)
reviews = Review.objects.filter(restaurant=item).all()
return render(request, 'p1/detail.html', {'item': item, 'reviews': reviews})
return HttpResponseRedirect('/p1/list/')
def delete(request, id):
item = get_object_or_404(Restaurant, pk=id)
if request.method == 'POST' and 'password' in request.POST:
if item.password == request.POST.get('password') or item.password is None:
item.delete()
return redirect('list')
return redirect('restaurant-detail', id=id)
return render(request, 'p1/delete.html', {'item': item})
def review_create(request, restaurant_id):
if request.method == 'POST':
form = ReviewForm(request.POST)
if form.is_valid():
new_item = form.save()
return redirect('restaurant-detail', id=restaurant_id)
item = get_object_or_404(Restaurant, pk=restaurant_id)
form = ReviewForm(initial={'restaurant': item})
return render(request, 'p1/review_create.html', {'form': form, 'item': item})
def review_delete(request, restaurant_id, review_id):
item = get_object_or_404(Review, pk=review_id)
item.delete()
return redirect('restaurant-detail', id=restaurant_id)
def review_list(request):
reviews = Review.objects.all().select_related().order_by('-created_at')
paginator = Paginator(reviews, 10)
page = request.GET.get('page')
items = paginator.get_page(page)
context = {
'reviews': items
}
return render(request, 'p1/review_list.html', context)
Author And Source
이 문제에 관하여([Django] CRUD 알아보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sorzzzzy/Django-CRUD-알아보기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)