Server/Django project 1 - shopping mall

12. Django order app 상품 주문하기 (2)

개발자킹콩 2020. 10. 7. 17:48

지난 수업에 이어 상품주문하기 2편이다!!!

이번엔 좀 어렵다잉!! 가즈아!!

 

 

목차 : 

1. request.session

2. db.transaction

3. 결과 확인

 

 


 

 

1. request.session

 

 

(1)

이제 해당 주문으로 인해 수량이 감소하는 것을 DB에 저장하도록 하는 코드를 작성할 것이다 .

 

order / forms.py

 

# 이제 사용자 정보를 들고와야한다.

# session을 가져오려면 form 안에서 request.session에 접근할 수 있어야 하는데

# 현재는 접근할 수 없다. session에 접근할 수 있도록 form을 변경할 것이다.

 

 

 

 

여기서 DB에 데이터를 저장하는 save()의 경우 어느 파일에서 하든 상관없지만,

FormView의 경우 값을 form으로 입력받으면, 그 값을 DB에 넣는 작업또한,

해당 form에서 하는 것이 유리하고 편할 것이다.

 

기본적으로 request에서 접근할 수 없기때문에 이 form안에서 view로 전달을 해줘야한다.

"생성자 함수"를 만들면서 request를 form에 전달할 수 있게끔 만들고

FormView와 form을 생성할 때 이 request를 전달할 수 있게 변경해보자

 

order / forms.py

 

 

이제부터 OrderForm을 객체로 생성하려면 request를 넣줘야한다.

이 Form을 생성하는 것은 "상품상세보기 페이지"에 있었다.

 

product / views.py

 

view이기에 self안에 request가 존재하고 OrderForm을 객체로 생성하려면

self.request를 인자로 전달해주어야 한다.

 

 

이렇게 되면 form class를 생성하면서 request를 전달하고

그렇게되면 OrderForm에 self.request 변수를 생성하고 전달받은 값을 변수로 유지한다.

이렇게 되면 우리는 OrderForm의 clean함수에서 request.session에 접근을 할 수 있다.

(이거 할라고 request작업을 해준 것이다.)

 

 

 

 

 

 

 

(2) 지금 현재 상황에서 수량을 입력하고 주문하기를 누를경우 에러가 발생한다.

 

http://127.0.0.1:8000/order/create/

 

 

이전에 작성한 product_detail.html에서 form tag의 정보를 입력받아 "/order/create/"로 form을 전달한다고 했는데 내부에서 FormView는 이 request라는 것을 모르기 때문에 얘를 넣지 않았다고 에러를 발생시킨다. 그렇기에 FormView안에서도 request를 전달할 수 있도록 만들어 줘야한다.

 

 

이러한 클래스기반의 view안에는 (FormView) 기본적으로 kwargs라는 함수가 존재한다. 

이 함수가 하는 역할은 form을 생성할 때, 어떤 인자값을 전달해서 만들건지를 결정하는 함수다.

이 함수를 덮어서 만들면 된다.

 

 

 

이렇게 되면 우선 에러는 발생하지 않는다.

주문하기를 누르면 정상적으로 success_url로 이동하게 된다.

 

 

 

 

 

 

(3)

이제 form에서 정상적으로 session에 접근할 수 있는지 print를 해본다.

order / forms.py / class OrderForm

 

그리고 주문하기 기능을 이용하면 session에 대한 정보가 출력될 것이다.

 

 

이제 늘 그렇듯 해당 Order 모델을 생성해서 DB에 저장하는 코드를 구현하면 된다. 

수량은 입력받은 그대로의 값을 사용하고,

product는 ForeignKey로 연결이 되어있기때문에 그 모델을 가져와야 한다.

해당 모델의 가져온 정보를 객체로 생성하여 저장하는 것이다. 

 

로그인이 되어있지 않으면 shopuser에 대한 정보가 없기에 저장되지 않을 것이고,

이제 값이 없을 때 에러를 띄우도록 하면 템플릿오류가 발생할 것이다. 왜?

로그인이 되어있지 않고 -> 오류가 발생했다고 표시할 템플릿이 없기 때문이다.

그렇다면 실패했을 때(정상적으로 주문되지 않았을 때) 주문을 진행중인 detail page로 이동을 시켜야 한다.

 

 

order / views.py

 

 

 

이제 해주어야 할 것은 view에서 form.product를 알고 있어야한다.

그래야 빨간색으로 표시한 링크로 이동할 수가 있잖아!!!

 

그러기 위해서는 아래와 같이 실패할 경우 form안에 product라는 변수에

현재 인지하고 있는 product값을 넣음으로써 form을 전달하는 것이다.

이렇게 되면 주문에 실패할 경우 다시 본 페이지로 돌아올 수 있다

 

 

 

 

 

이제 수량하나로 주문하기를 눌러보니

admin페이지에서 주문이 정상적으로 들어왔음을 확인할 수 있다.

 

 

 

 

 

 


 

 

 

 

2. db.transaction

 

우선 재고를 관리하고 있는데 재고를 줄이는 코드가 존재하지 않는다.

그리고 여러개의 모델을 한번에 처리하기 위해 트렌젝션이라는 것도 배워야한다.

 

이제 트렌젝션이라는 것을 통해 주문이 들어가면서 자동으로 product의 재고를 줄이도록 할 것이다.

트렌젝션이란 하나의 단위이다.

트렌젝션으로 만든다는 것은 일련의 여러동작을 하나의 동작으로 처리하겠다.

전체가 다 성공하면 성공을 한것이고, 하나라도 실패를하면 실패한 것으로 간주하고 rollback으로 실제 반영이 안 되게 한다.

 

주문하기의 경우

  • 주문 정보가 비어있지않고 들어가야 한다.
  • 상품의 재고가 줄어야 한다.

 

 

이 두가지가 모두 일어나야 하는데 하나라도 실패하면 이것은 rollback으로 반영되지 않아야 한다.

이렇게 일관되게 여러개의 동작이 한번에 처리되도록 하는 것이 트렌젝션이다.

기본적으로 데이터베이스DB에서 제공을 하는 기능이다.

장고에서는 이를 편히 쓰도록 또 제공을 한다네~!!!

 

 

order / forms.py

 

transaction.atomic()을 with로 감싸면서 위와 같이 사용하게 되면 

with안에서 일어나는 db와 관련된 동작들은 transaction으로 동작하게 된다.

 

order / forms.py

 

다음과 같이 재고가 줄어들게 만들었다. 

기능을 보기위함으로 비교적 간단하게 만들었다.

 

 

 

 

 


 

 

 

3. 결과 확인

 

 

현재 로그인이 되어있는 상태이다.

 

 

 

3번 물건의 경우 현재 재고가 123개 존재한다.

 

 

11개를 주문하면 정상적으로 동작하여 올바른 결과가 나온다.

 

 

 

 

 

 

 

 

 

 

여기까지!! 오늘도 감코!!