본문 바로가기
Web/Django

[Django] CRUD 구현

by DUSTIN KANG 2023. 11. 29.

 

오늘은 Django에서 모델을 만들어 보고, 실제로 CRUD 처리를 구현하는 연습을 포스팅하려고 한다.

모델 생성

먼저, 데이터를 처리하기 위해 모델을 생성해야 한다. SQL를 통해 이전 하는 방법도 직접 Model을 작성하는 방법도 있다.

 

모델을 간단하게 정의했다.

 

여기서, 특별한 건, `ForeignKey`(외래키)를 사용했다는 것이다.

외래키 작성의 파라미터로 참조할 테이블, 개체 관계 이름, 개체시 동작을 넣는다.

  • 참조할 테이블 : 연결할 모델 클래스를 가리키며 해당 외래키에서 어떤 테이블을 참조할지를 의미한다.
  • 관계상 이름(related_name) : 개체 관계에 사용할 이름을 나타내는데 역방향에서 참조할 때 사용하는 이름이다. Categoty 테이블에서 category 속성을 통해 Memo의 category를 역참조한다. 
  • 개체 삭제시 수행동작(on_delete / on_update) : Category 모델이 삭제될때 Memo모델이 미치는 영향을 말한다.
  • DB 필드 이름(db_column) : 테이블에 정의되는 이름을 말한다. category 필드가 데이터베이스 테이블에서 category_id라는 열 이름을 가지도록 지정합니다

개체 삭제시 수행동작으로 `CASCADE`, `PROTECT` `SET_NULL` `SET(func)`, `DO_NOTHING` 등이 있다. 

모델 생성이 끝났으면, migration을 통해 모델을 마이그레이션 하고, 테이블에 데이터가 어떻게 이루어졌는지 확인해보자.

VSCode 확장 프로그램으로 `SQLite`를 사용하면 쉽게 확인할 수 있다.

 

직접 데이터를 확인할 수 있고 넣을 수 있다고 한다.

 

 

Queryset API 사용하기

QuerySet API는 Django의 ORM을 이용해서 데이터베이스를 조작하는 것을 말한다.

django shell을 통해 여러가지 코드를 테스트할 수 있다. 

python manage.py shell

 

 

CREAT

 

데이터를 생성할 때, 이외에도 `class.objects.create()`를 이용해 생성이 가능하다.

블로그 해당 페이지를 참고하면 된다.

 

CRUD 생성하기

이제 본론으로, CRUD를 생성하는 내용이다.

먼저, 프로젝트와 앱을 생성하고 간단하게 View를 작성하고 URL를 라우팅하는 부분까지 완료해야한다.

 

우리는 아래 처럼, Memo리스트를 완성하고 해당 메모로 들어가면 메모의 자세한 내용과 CRUD 처리를 하는 부분을 진행하려고 한다.

 

게시글 조회(READ)

`Memo.objects.all()`을 통해 전체 메모 데이터를 불러오고 context에 담아 템플릿에 넘겼다.

템플릿은 반복문을 통해 메모에 있는 필드 데이터를 활용해 작성한다.

 

우선 연습이기 떄문에 bootstrap에서 간단히 알림창을 대신했다,,

 

상세 메모 조회(READ)

메모 데이터를 삭제, 수정, 추가하려면 먼저 상세 데이터에 대해 조회처리가 필요하다.

url pattern에 변수 라우팅을 활용해 게시물을 조회할 수 있도록 pk를 받는다.

 

urlpatterns = [
    path('', list_view, name="index"),   
    path('<int:pk>', detail_view, name="detail"),
]

 

 

이전, 메모 목록 조회와 비슷하게 작성한다.

 

 

이번엔, 목록 페이지와 상세 페이지를 연결 시켜줘야한다.

목록 템플릿에서 `url` 태그를 통해 상세 페이지와 연결해줄 수 있는데, url pattern에서 작성했었던 namespace를 이용해 연결시키며, 해당 데이터의 값도 전달한다.

 

 

 

메모 생성 (CREATE)

메모를 생성하기 위해 사용자가 입력을 받고 Submit을 눌렀을 때 DB에 데이터를 저장하는 코드를 작성해야한다.

다음과 같이 메모 입력을 받기 위한 페이지를 가져올 때 `GET` 메소드로 가져온다.

또한, 입력을 받고 제출을 눌렀을 때 DB에 데이터를 생성하는 `POST` 메소드도 이용한다.

 

 

 

생성할 때, CSRF 공격을 막기 위해 POST 요청이 외부에서 보낸게 아닌지 검증하기 위해 이 토큰을 사용한다. 하지만 이 토큰은 내부 URL의 경우 해당하면 외부 URL의 경우는 토큰이 유출될 위험이 있기 때문에 사용하면 안된다.

 

메모 삭제(DELETE)

메모를 삭제하기 위해 delete url을 추가하고 delete 뷰를 정의한다.

Model 객체를 자세히 들여다 보면 `delete()`함수가 내장되어 있기 때문에 그대로 쓰면 된다.

그러나, 그대로 썼다간 `/memo/1/delete/` 이런 식으로 GET으로 들어가게되면 삭제될 것이다. 이를 방지하기 위해 아래 코드 처럼 작성한다. 지금은 POST를 사용했지만 어떤 경우에는 DELETE를 쓰는 경우도 있으니 경우에 따라 쓰면 된다.

def delete_view(request, pk):
    memo = Memo.objects.get(pk=pk)
    if request.method == 'POST':
	    memo.delete()
    return redirect('index')
    
    
<a href="{% url 'delete' memo.pk %}"><button type="button" class="btn btn-danger btn-sm" >삭제하기</button></a>

 

만약 정말 삭제에 대한 페이지를 통해 삭제하고 싶으면 POST와 GET 방식을 따로 지정해두면 좋을 것 같다.

<form action="{% url 'articles:delete' memo.pk %}" method="POST">
    {% csrf_token %}
    <button class="btn btn-danger">삭제</button>
</form>

 

 

메모 수정(UPDATE)

메모를 수정하는 부분은 생성하는 법과 유사하다. 사용자가 입력 페이지를 가져오고 입력을 다시 받은 후 DB에 다시 저장한다.

이때, 템플릿에는 수정된 데이터를 가져와야 하기 때문에 `value` 옵션을 추가해 기존 데이터 값을 넣어준다.

 

 

아래 get인 경우와 post인 경우를 나누어 작업

 

중간과정

 

데코레이터 사용하기

데코레이터를 사용하면 함수를 고치지 않고 기능을 덧붙일 수 있다.

예를들어, 메모를 생성하는 함수인 경우, 우리는 POST의 경우에만 실행해야 한다. 하지만 URL로 접근하더라도 생성이 되는 문제가 발생한다.  이때, POST 방식일 때만 데이터를 처리할 수 있게 `@require_http_methods(['POST'])`를 작성하거나 `require_POST` 를 작성하면 POST 방식만 처리할 수 있다.

from django.views.decorators.http import require_POST

 

 

 

이렇게 사용하면, 필요한 HTTP method만 사용해서 처리할 수 있다. 

여기서, `require_safe`는 GET 방식만 처리하는 것인데 기존 GET보다 권장하는 방법이라고 한다. 

HTTP Methods

get 조회 READ
post 생성 CREATE
put 수정 UPDATE
delete 삭제 DELETE