커스텀 액션 추가

Codren·2021년 5월 25일
0

Django Admin

목록 보기
6/13
post-custom-banner

Section 1. 커스텀 액션 추가

1. 액션 기능

  • 목록 페이지에서 행 체크박스 체크 후 원하는 액션 실행하는 기능



2. admin.py 수정

  • queryset 으로 체크박스에 체크한 행들이 넘어옴
  • refund () 함수 선언 후 actions 에 지정
  • 주문 환불 시 Product 의 quantity 값을 수정하는 DB 작업이므로 transaction.atomic() 사용
  • queryset 의 모델(테이블)을 추출하기 위해 ContentType.objects.get_for_model() 사용
    (from django.contrib.contenttypes.models import ContentType)

qs = queryset.filter(~Q(status='환불'))  		# status 속성이 '환불'이 아닌 행들만 추출
ct = ContentType.objects.get_for_model(queryset.model)  # queryset의 model(테이블)을 추출 -> '주문' 추출됨

obj.product.stock += obj.quantity			# order 테이블은 product 테이블을 참조하고 있으므로 참조하고 있는 해당 product의 stock을 order의 quantity 만큼 다시 증가시킴 
qs.update(status='환불')					# qs 에 있는 모든 행들의 status 속성을 '환불'로 업데이트

actions = [ refund ] 					# 액션에 사용자 정의 액션인 refund 추가




3. Q

  • queryset 조회문에서 filter (where문)를 적용할 때 논리적 연산이 수행될 수 있도록 객체를 캡슐화
  • '~' NOT  /  ' ' AND  /  '|' OR
  • from django.db.models import Q



4. LogEntry

  • Admin 페이지에서 수행하는 모든 활동들을 기록하는 Log
  • from django.contrib.admin.models import LogEntry, CHANGE
  • LogEntry.objects.log_action() 은 액션 log 를 직접 생성하는 함수
LogEntry.objects.log_action
(       
        user_id = request.user.id,		# 해당 액션을 수행하는 admin user의 id
	content_type_id = ct.pk,		# 해당 액션의 모델이 어떤 모델이고 어떤 타입인지 (log에 출력되는 모델명)
	object_id = obj.pk,			# 모델의 어떤 행인지 행의 id
	object_repr = '주문 환불',		# 액션 log에 출력될 내용
	action_flag = CHANGE,			# 액션 log에 출력되는 아이콘
	change_message = '주문 환불'
 )




5. 커스텀 액션 수행 결과




error


1. 같은 상품의 주문 환불 시 재고가 제대로 변경되지 않는 error

  • 아래와 같이 같은 상품 (test_product4)의 주문을 환불하면 상태는 '환불'로 제대로 변경되지만 상품의 재고는 둘 다 적용되지 않고 하나만 적용되는 error

  • 원인
    - test_product4의 재고가 100개라면 queryset으로 2개의 주문 항목을 불러올 때 둘 다 obj.product.stock의 수가 100개이기 때문에 트랜잭션 충돌이 일어나게 됨 (갱신 분실)
    즉, 첫 번째 항목을 환불할 때 stock의 값을 변경했더라도 두 번째 항목을 환불할 때 또 다시 100개를 기준으로 작업을하고 해당 결과를 save()하기 때문에 첫 번째 stock 변경 값은 분실(lost)됨

  • 해결 방법
    - 현재 test_product4의 stock 값과 환불하려는 주문 항목의 test_product의 stock 값이 일치하면 그대로 작업을 수행하고 일치하지 않다면 queryset으로 불러온 이후에 값이 변경됬다는 의미이므로 변경된 값을 기준으로 작업을 수행
post-custom-banner

0개의 댓글