장고 프로젝트(맛집 공유 사이트 만들기) - 템플릿 설정하기 Django Project Restaurant share - 2
https://bmil2011s.tistory.com/25 장고 프로젝트(맛집 공유 사이트 만들기) 기본 설정 Django Project Restaurant share - 1 ToDoList 만들기 프로젝트를 무사히 마치고, 두 번째 프로젝트인 맛집 공유 사이트 만들기
bmil2011s.tistory.com
이전 글에서는 기본 세팅과 템플릿을 가져오는데 성공하여 기본 웹페이지 로직을 갖추었다면, 이제 본격적으로 이 프로젝트의 목적을 구현하기 위한 CRUD 기능들을 구현해보자. Category에 대한 CRUD와 Restaurant에 대한 CRUD 로 크게 두 가지 CRUD를 구현할 예정이다.
0. 참고 : 맛집 공유 사이트 메인 화면
1. Category CRUD
1-1 Create
- 먼저 Category 의 + 버튼에 대한 create 기능부터 진행해보자.
- 처음으로 해야 하는 것은Category에 대해 정의하는 것이다. Category는 단순히 이름만 가진다(ex : 한식, 중식, 일식 등).
- 우리는 Cateogry에 대해 맛집을 분류하는 기준이자, 하나의 맛집이 하나의 Category에 속하게 된다고 정할 것이다. 물론 "하나의 맛집이 하나의 Category에 속하는 기능 구현 방법"은 이후에 다루고, Category 모델*은 단순히 이름만 가지는 것으로 다음과 같이 코드를 작성하여 정의하겠다.
*MTV의 Model
- 모델 정의 후에는 python manage.py makemigrations 와 python manage.py migrate 명령어를 순차적으로 실행하여 데이터 베이스에 반영해주자.
- 다음으로 새로운 기능을 구현할 때는? views.py를 다음과 같이 수정해주자.
- redirect 함수를 위해 3번째 줄 import, model 기능 사용을 위해 4번째 줄 import
- User가 문자열 입력 후 추가 버튼을 눌렀을 때 POST 방식으로 전달되므로 requset.post를 이용하여 category_name 이라는 변수에 담고,
- Category 모델에 이 값을 넣은 뒤, save() 함수를 이용하여 데이터베이스에 저장
- 마지막으로 추가 버튼을 누른 뒤 이 모든 기능을 처리하고, user는 메인 화면으로 다시 돌아가야하므로 return 이하의 코드를 해라. 무엇을? 돌아가라. 어디로? (index링크로).
- 다음으로 새로운 기능에 대한 새로운 경로들이 만들어졌으므로 다음과 같이 urls.py 에 대한 수정이 필요하다.
- 각 기능이 처리된 후에 특정 화면으로 redirect하기 위한 각 path에 name 설정도 이루어졌다.
1-2 Read
- Read 기능을 구현한다는 것은 데이터베이스에서 Category 모델로 생성된 데이터를 가져와서 화면으로 뿌려 준다는 것이다. 따라서 Category 모델로 생성된 모든 데이터를 가져오기 위해 views.py를 추가로 수정한다.
- 8번째 줄 내용은 Category 모델의 모든 객체를 가져와라, 9번째 줄 내용은 가져온 내용을 content 딕셔너리에 담아라, 10번째 줄에서 render 함수 마지막에 해당 딕셔너리를 함께 전달해주도록 했다.
- 기능을 구현하였으므로 다음에는 템플릿을 수정해주자(index.html에서 해당 cotent를 받아 보여주면 되므로)
- 기존 index.html 219번째 줄 <li class="categoy deactive">한식</li> 부터 272번째 줄 </ul> 까지 삭제하고, 해당 위치에 아래 코드와 같이 작성하자.
<ul class="restaurantListDiv nav nav-pills nav-stacked">
{% 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 %}
</ul>
<a href="restaurantCreate/" class="sendBtn btn btn-info" role="button">맛집 추가하기</a>
- 수정하고 추가한 내용들이 정상적으로 작동한다면 아래와 같이 메인화면을 확인해볼 수 있다.
- 또한 category는 index화면 뿐 아니라 + 버튼을 눌렀을 때 나오는 화면에서도 나타나야 하므로 방금 진행한 방식과 동일하게 views.py 수정 후 html 템플릿을 수정하자.
- 여기까지 알맞게 수정하였다면 main 화면(index.html)에서 뿐만아니라 아래 화면에서도 다음과 같은 화면을 볼 수 있다.
- 그런데 여기서 삭제할 수도 없는 기본그룹이란 무엇일까? restaurant 가 생성될 때 무조건 1개의 category에 속해야 하기 때문에 존재한다. 우리가 추가하는 category는 삭제가 가능하기 때문에, 모든 category가 삭제되었을 때를 위함이다.
하지만 현재 기본 그룹은 실제 데이터베이스에 존재하는 것이 아니고 단순히 html 템플릿에 의해 문자열만 출력되는 중이다. 이를 실제 데이터 베이스 데이터로 만들어주고 넘어가려고 한다.
- 먼저 기본 그룹을 웹페이지에서 직접 추가해주고, python manage.py dbshell로 데이터 베이스 shell에 접속한다.
- 다음 명령어 .tables로 테이블들을 파악하고, 이후 우리가 확인하려는 shareRes_category 테이블의 데이터들을 확인하기 위해 select * from shareRes_category; 명령어를 입력한다.
- 이때 기본 그룹 이라고 적힌 줄 좌측 번호를 확인해보면 해당 카테고리 id가 3임을 확인할 수 있다 .quit 명령어로 데이터베이스를 빠져나오자.
- 다시 html 템플릿을 확인해보면 기본 그룹을 나타내는 코드는 84~86번째 줄이다.
- 해당 줄을 삭제하고, 다음과 같이 코드를 수정해주자. 83번째줄(첫번째줄) 부터 102번째줄(마지막줄)을 다음과 같이 구석구석 수정되었으니 확인해보자
* 93번째 줄 내용 추가 >>> 에 따른 101번쨰 줄 내용 추가
* 97번째 줄 내용은 이후 삭제 기능을 추가할 때를 위해 hidden type 인 곳 value 값에 category id를 추가해주었다.
<div class="inputDiv">
{% 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 %}
{% for category in categories %}
{% if category.id != 3 %}
<form action=" " method="POST">{% csrf_token %}
<div class="input-group">
<span class="input-group-addon" id="" style="border:1px solid #ccc; border-radius: 4px;">{{ category.category_name }}</span>
<input type="hidden" name="categoryId" id="categoryId" value="{{category.id}}"/>
<input type="submit" class="resAddBtn btn btn-danger" role="button" value="삭제"/>
</div>
</form>
{% endif %}
{% endfor %}
- 다음과 같이 코드를 수정해주면 겉보기에는 화면에서 다른 점이 없으나, 이전에는 기본 그룹이 단순히 문자열로 출력되고 있던 것이었고, 현재는 실제 데이터 베이스에 존재하는 것을 가져와 보여주는 것이다.
1-3 Update Delete
- Update 기능 구현은 이후 restaurant에서 구현해보도록 하고, 마지막 Delete 기능을 구현해보자
- Delete를 기능을 위한 html 수정은 거의 된 상태이고(이전에 추가함), 사용자가 삭제 버튼을 눌렀을 때 어떠한 url로 갈 것인지, 그리고 그 url에 대한 처리만 남아 있다.
- 먼저 삭제 버튼을 눌렀을 때, "http.../categoryCreat/delete로 이동시키고자 하므로 다음과 같이 action 값을 수정하자.
- 다음으로 기능 구현을 위해서는 views.py 에 새로운 기능을 가진 함수를 추가해주면 된다.
- 함수 코드의 흐름을 보면 user가 삭제 버튼을 눌렀을 때 hidden 타입의 input 태그의 value 값을 받아오고 해당 값을 통해 Category 모델에서 실제 데이터를 get 함수로 찾아온다. 그렇게 불러온 값을 delete 함수로 삭제하고 다시 Category 생성 페이지로 돌아간다.
- 자연스럽게 다음의 기능까지 url을 가져올 수 있도록 urls.py를 다음과 같이 수정해주자.
이렇게 Category에 대한 CRUD는 완료가 된다.
* 이 글은 Django 한그릇 뚝딱(문범우, 2019)의 챕터 3 "맛집 공유 사이트 만들기" 내용을 참고하였음(틀린 부분 약간 수정됨).