본문 바로가기
웹 개발 실습/Django

[Django]_맛집 공유 사이트 만들기 (2) READ, DELETE 그리고 Restaurant에 대한 CRUD

by ssolLEE 2023. 7. 30.
반응형

 

이 프로젝트도 마찬가지로 책 'Django 한 그릇 뚝딱'의 Chapter 3을 보며 실행해보았습니다. 책의 저자님께 다시 한 번 감사말씀 드립니다.

 

CRUD - READ

이제 사용자가 생성한 Category를 화면에서 확인할 수 있도록 READ를 구현하겠습니다. 

  • RestaurantShare > shareRes > views.py로 이동하여 코드를 수정합니다.

메인 화면을 보여주는 index 함수를 수정한다.

  • 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로 이동합니다. 함수를 수정합니다.

res_id를 통해 일치하는 restaurant 데이터를 가져오고, 이를 content에 담아서 함께 전달해 주었다.

  • 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'),

path의 순서가 섞이면 에러가 발생한다.

  • 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'))
  • 웹 사이트를 새로고침한 후에 삭제를 확인한다.

삭제 작업까지 잘 된다.

 

여기까지 수고 많으셨습니다. 

다음 포스팅에서는 마지막으로 '이메일 보내기' 를 해보겠습니다.

 

감사합니다.