반응형

이 프로젝트도 마찬가지로 책 'Django 한 그릇 뚝딱'의 Chapter 3을 보며 실행해보았습니다. 책의 저자님께 다시 한 번 감사말씀 드립니다.
CRUD - READ
이제 사용자가 생성한 Category를 화면에서 확인할 수 있도록 READ를 구현하겠습니다.
- RestaurantShare > shareRes > views.py로 이동하여 코드를 수정합니다.

- Category 모델로 정의된 모든 객체를 불러오고, 9번째 줄에서는 이를 content 딕셔너리에 담는다. 그리고 render함수 마지막에 이 딕셔너리를 함께 전달하는 것이다. 이제 index.html에서 해당 content를 받아 사용자에게 보여주도록 설정합니다.
- RestaurantShare > shareRes > templates > shareRes > index.html 로 이동합니다.
- 219줄(~272줄까지 삭제합니다.


- 삭제한 위치에 하단의 코드를 작성합니다. 아래의 코드 블럭을 그대로 붙여넣기 하시면 줄도 맞습니다.
{% for category in categories %}
<li class="category deactive">{{ category.category_name }}</li>
<ul class="restaurantList">
<div class="input-group">
<span class="input-group-addon">
<input name="check1" id="check1" type="checkbox">
</span>
<a href="restaurantDetail/1"><input name="res1" id="res1"
type="text" class="form-control" disabled style="cursor: pointer;" value="1"></a>
</div>
<div class="input-group">
<span class="input-group-addon">
<input name="check2" id="check2" type="checkbox">
</span>
<a href="restaurantDetail/2"><input name="res2" id="res2"
type="text" class="form-control" disabled style="cursor: pointer;" value="2"></a>
</div>
</ul>
{% endfor %}
- 다시 웹 페이지를 확인합니다.

데이터베이스에 저장된 category 출력하기
위의 방법과 동일하게 진행합니다.
- RestaurantShare > shareRes > views.py로 이동하여 categoryCreate함수를 수정합니다.

- RestaurantShare > shareRes > Templates > shareRes > categoryCreate.html 로 이동합니다.
- 88번째 줄~94번째 줄까지 삭제합니다.


- 삭제한 위치에 다음 코드를 작성합니다.
{% for category in categories %}
<form action="" method="POST">{% csrf_token %}
<div class="input-group">
<span class="input-group-addon" id=""style="border:1px solid #ccc; border-radius: 4px;">한식</span>
<input type="hidden" name="categoryId" id="categoryId" value=""/>
<input type="submit" class="resAddBtn btn btn-danger" role="button" value="삭제"/>
</div>
</form>
{% endfor %}

- 웹 사이트를 확인합니다.

웹 사이트 화면의 '기본 그룹'을 데이터베이스에 데이터로 만들기
- 카테고리 추가하기 화면에서 카테고리명 입력 칸에 "기본 그룹"을 큰따옴표 없이 입력해 추가합니다. 그리고 해당 id를 알기 위해 데이터베이스 shell에 접속합니다.(terminal에서 다음 명령어를 입력합니다.)
python manage.py dbshell
- .table을 입력합니다.

- SELECT * FROM shareRes_category; 를 입력합니다.

- .quit을 눌러 shell에서 빠져나옵니다.
- RestaurantShare > shareRes > Templates > shareRes > categoryCreate.html 로 이동합니다.
- "기본 그룹"을 나타내는 84~86번줄을 삭제합니다.

- 해당 위치에 다음 코드를 추가합니다.
{% for category in categories %}
{% if category.id == 3%}
<div class="input-group">
<span class="input-group-addon" style="border: 1px solid #ccc; border-radius: 4px;">{{ category.category_name }}</span>
</div>
{% endif %}
{% endfor %}

CRUD - DELETE
- RestaurantShare > ShareRes > templates > shareRes > categoryCreate.html 로 이동합니다.
- <form>태그 의 action 값을 다음과 같이 설정합니다.

- RestaurantShare > ShareRes > urls.py로 이동합니다. path를 추가합니다.
path('categoryCreate/delete', views.Delete_category, name='cateDelete')
- RestaurantShare > ShareRes > views.py로 이동합니다. 함수를 정의합니다.
def Delete_category(request):
category_id = request.POST['categoryId']
delete_category = Category.objects.get(id = category_id)
delete_category.delete()
return HttpResponseRedirect(reverse('cateCreatePage'))
- 이제 삭제 기능이 작동합니다.
Restaurant에 대한 CREATE
- '맛집 추가하기'를 클릭하면 나오는 카테고리 항목을 수정하고자 합니다.
- RestaurantShare > ShareRes > views.py로 이동합니다. 함수를 정의합니다.
def restaurantCreate(request):
categories = Category.objects.all()
content = {'categories' : categories}
#return HttpResponse("restaurantCreate")
return render(request, 'shareRes/restaurantCreate.html', content)
- RestaurantShare > ShareRes > templates > shareRes > restaurnatCreate.html로 이동합니다.
- 카테고리를 나타내는 98~100번째 줄을 삭제합니다.

- 삭제한 곳에 다음을 입력합니다.
{% for category in categories %}
<option value="{{category.id}}">{{category.category_name}}</option>
{% endfor %}

- 웹 페이지를 새로 고침하면 다음과 같이 카페고리가 바뀐 것을 확인할 수 있습니다.

- 다음과 같이 코드를 수정하면 어떻게 될까요?(RestaurantShare > ShareRes > templates > shareRes > restaurnatCreate.html)

이렇게 하면 맛집 추가하기 화면에 접근했을 때 이상 없이 사용자의 입력만 있으면 됩니다.
- RestaurantShare > ShareRes > models.py 로 이동하여 restaurant에 대한 model 정의와 데이터베이스 반영을 하겠습니다.
- 다음 코드를 추가합니다.
class Restaurant(models.Model):
category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT, default=3)
restaurant_name = models.CharField(max_length=100)
restaurant_link = models.CharField(max_length=500)
restaurant_content = models.TextField()
restaurant_keyword = models.CharField(max_length=50)
- 데이터베이스에 반영하겠습니다. 다음의 명령어를 차례로 입력합니다.
python manage.py makemigrations
python manage.py migrate
- '맛집 추가' 버튼을 클릭했을 때 CREATE 기능을 하기 위해 url을 설정하겠습니다.
- RestaurantShare > ShareRes >templates > shareRes > restaurnatCreate.html로 이동합니다.
- 93번째 줄의 <form>태그의 action값을 채워줍니다.

- RestaurantShare > ShareRes > urls.py로 이동합니다. path를 추가합니다.
path('restaurantCreate/create', views.Create_restaurant, name='resCreate'),
- RestaurantShare > ShareRes > views.py로 이동합니다. 함수를 정의합니다.
def Create_restaurant(request):
category_id = request.POST['resCategory']
category = Category.objects.get(id = category_id)
name = request.POST['resTitle']
link = request.POST['resLink']
content = request.POST['resContent']
keyword = request.POST['resLoc']
new_res = Restaurant(category=category, restaurant_name = name, restaurant_link=link,
restaurant_content=content, restaurant_keyword=keyword)
new_res.save()
return HttpResponseRedirect(reverse('index'))
- 여기까지 잘 했다면, 맛집 추가하기 화면에서 내용 입력 후 '맛집 추가!'를 누르면 메인 화면으로 갈 것입니다.
Restaurant에 대한 READ
- 추가된 맛집을 사용자들이 볼 수 있도록 하겠습니다.
- RestaurantShare > ShareRes > views.py로 이동합니다. index함수를 수정합니다.

- RestaurantShare > ShareRes >templates > shareRes > index.html로 이동합니다.
- 223~237번째 줄을 삭제합니다.


- 삭제한 자리에 다음 코드를 입력합니다.
{% for restaurant in restaurants %}
{% if restaurant.category == category %}
<div class="input-group">
<span class="input-group-addon">
<input name="checks" id="check{{restaurant.id}}" type="checkbox"
value="{{restaurant.id}}">
</span>
<a href="restaurantDetail.html/{{restaurant.id}}">
<input name="res{{restaurant.id}}" id="res{{restaurant.id}}" type="text"
class="form-control" disabled style="cursor: pointer;"
value="{{restaurant.restaurant_name}}">
</a>
</div>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
- 웹 페이지를 새로고침하면 다음과 같이 카테고리별 restaurant이 보입니다.

- RestaurantShare > shareRes > urls.py로 이동합니다. path를 수정합니다.

- RestaurantShare > ShareRes > views.py로 이동합니다. index함수를 수정합니다.

- RestaurantShare > ShareRes >templates > shareRes > restaurnatDetail.html로 이동합니다.
- 다음과 같이 코드를 수정합니다. 각각에 대해서 restaurant에 대한 정보를 추가하는 작업입니다.

- 웹 페이지를 새로고침을 한 후에 카테고리 속 restaurant을 클릭하면, 아까 Create할 때 입력한 내용을 확인할 수 있습니다.

Restaurant에 대한 UPDATE
- "수정하기" 기능을 추가하겠습니다.
- RestaurantShare > shareRes >templates > shareRes > restaurnatDetail.html로 이동합니다.
- 115번쨰 줄에 다음의 코드를 입력합니다.
<a href="./updatePage/{{restaurant.id}}" class="resAddBtn btn btn-danger" role="button">수정하기</a>

- 웹 페이지를 새로고침하면 "수정하기"버튼이 생성된 것을 확인할 수 있습니다.

- RestaurantShare > shareRes > urls.py로 이동합니다. path를 추가합니다.
path('restaurantDetail/updatePage/<str:res_id>', views.restaurantUpdate, name='resUpdatePage')
- RestaurantShare > shareRes > views.py로 이동합니다. 함수를 정의합니다.
def restaurantUpdate(request, res_id):
return HttpResponse('restaurant을 수정할 페이지')
- update화면은 create화면에서 크게 다르지 않을 것이므로, restaurantCreate.html파일을 복사한 후, 이름을 restaurantUpdate.html로 수정합니다.
- RestaurantShare > shareRes >templates > shareRes > restaurnatUpdate.html로 이동합니다.
- 내용을 수정합니다.


- RestaurantShare > shareRes > views.py로 이동합니다. 함수를 수정합니다.
def restaurantUpdate(request, res_id):
categories = Category.objects.all()
content = {'categories' : categories}
return render(request, 'shareRes/restaurantUpdate.html', content)
# return HttpResponse('restaurant을 수정할 페이지')
- 웹 사이트를 새로고침한 후 '수정하기'를 누르면 다음과 같이 화면이 뜹니다.

- 이제 데이터를 함께 넘겨주어 html 화면에서 출력해보겠습니다.
- RestaurantShare > shareRes > views.py로 이동합니다. 함수를 수정합니다.

- RestaurantShare > shareRes >templates > shareRes > restaurnatUpdate.html로 이동합니다.
- 다음과 같이 수정합니다. (value 값 추가)
# 99번째 줄
{% if category == restaurant.category %}
# 113번째 줄
<input id="resLink" name="resLink" type="text" class="form-control" placeholder="관련 링크를 입력해주세요." aria-describedby="sizing-addon2"
value="{{restaurant.restaurant_link}}">
# 118번째 줄
<textarea id="resContent" name="resContent" cols="90" rows="10" placeholder="상세 내용을 입력해주세요.">{{restaurant.restaurant_content}}</textarea>
# 120번째 줄 태그
<div class="input-group">
<span class="input-group-addon" id="sizing-addon2">장소 키워드</span>
<input id="resLoc" name="resLoc" type="text" class="form-control" placeholder="장소 키워드를 입력해주세요." aria-describedby="sizing-addon2"
value="{{restaurant.restaurant_keyword}}">
- <form>태그의 action값을 수정합니다.

- 120번째 줄 <div>태그 맨 뒤에 <input>태그를 추가합니다.(코드 블럭에서 여섯번째 줄 추가) & 마지막 줄 '맛집 수정' 수정
<div class="input-group">
<span class="input-group-addon" id="sizing-addon2">장소 키워드</span>
<input id="resLoc" name="resLoc" type="text" class="form-control" placeholder="장소 키워드를 입력해주세요." aria-describedby="sizing-addon2"
value="{{restaurant.restaurant_keyword}}">
</div>
<input type="hidden" id="resId" name="resId" value="{{restaurant.id}}"/>
<input type="submit" class="resAddBtn btn btn-info" role="button" value="맛집 수정!"/>
- RestaurantShare > shareRes > urls.py로 이동합니다. path를 추가합니다.
path('restaurantDetail/updatePage/update', views.Update_restaurant, name='resUpdate'),

- RestaurantShare > shareRes > views.py로 이동합니다. 함수를 정의합니다.
def Update_restaurant(request):
resId = request.POST['resId']
change_category_id = request.POST['resCategory']
change_category = Category.objects.get(id = change_category_id)
change_name = request.POST['resTitle']
change_link = request.POST['resLink']
change_content = request.POST['resContent']
change_keyword = request.POST['resLoc']
before_restaurant = Restaurant.objects.get(id = resId)
before_restaurant.category = change_category
before_restaurant.restaurant_name = change_name
before_restaurant.restaurant_link = change_link
before_restaurant.restaurant_content = change_content
before_restaurant.restaurant_keyword = change_keyword
before_restaurant.save()
return HttpResponseRedirect(reverse('resDetailPage', kwargs={'res_Id' : resId}))
- 웹 사이트를 새로고침 하고 맛집 수정을 해보겠습니다.

Restaurant에 대한 DELETE
- RestaurantShare > shareRes >templates > shareRes > restaurnatDetail.html로 이동합니다.
- <form>태그를 추가합니다.
<form action="./delete" method="POST">{% csrf_token %}
<input type="hidden" id="resId" name="resId" value="{{restaurant.id}}"/>
<input type="submit" class="resAddBtn btn btn-danger" value="삭제하기">
</form>

- RestaurantShare > shareRes > urls.py로 이동합니다. path를 추가합니다. 최종적으로 완성될 urls.py 코드를 입력하겠습니다. 순서가 섞이지 않도록 주의해주세요.
# shareRes > urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('restaurantDetail/delete',views.Delete_restaurant, name='resDelete'),
path('restaurantDetail/<str:res_id>',views.restaurantDetail, name='resDetailPage'),
path('restaurantDetail/updatePage/update',views.Update_restaurant, name='resUpdate'),
path('restaurantDetail/updatePage/<str:res_id>',views.restaurantUpdate, name='resUpdatePage'),
path('restaurantCreate/',views.restaurantCreate, name='resCreatePage'),
path('restaurantCreate/create',views.Create_restaurant, name='resCreate'),
path('categoryCreate/',views.categoryCreate, name='cateCreatePage'),
path('categoryCreate/create',views.Create_category, name='cateCreate'),
path('categoryCreate/delete',views.Delete_category, name='cateDelete'),
]
- RestaurantShare > shareRes > views.py로 이동합니다. 함수를 정의합니다.
def Delete_restaurant(request):
res_id = request.POST['resId']
restaurant = Restaurant.objects.get(id = res_id)
restaurant.delete()
return HttpResponseRedirect(reverse('index'))
- 웹 사이트를 새로고침한 후에 삭제를 확인한다.

여기까지 수고 많으셨습니다.
다음 포스팅에서는 마지막으로 '이메일 보내기' 를 해보겠습니다.
감사합니다.
'웹 개발 실습 > Django' 카테고리의 다른 글
| [Django]_엑셀 계산 사이트 만들기 (1) app의 웹 사이트, admin 화면 만들기 (0) | 2023.08.01 |
|---|---|
| [Django]_맛집 공유 사이트 만들기 (3) 이메일 보내기 (0) | 2023.07.31 |
| [Django]_맛집 공유 사이트 만들기 (1) 프로젝트 구성 & CREATE (0) | 2023.07.30 |
| [Django]_ToDoList 만들기 (5) 데이터베이스에 저장하기 (0) | 2023.07.30 |
| [Django]_ToDoList 만들기 (4) 입력한 메모 출력하기 (0) | 2023.07.30 |