장고 - 관리자 사이트의 결제정보 csv 파일

  • 이번 포스트에서는 온라인 쇼핑몰 사이트를 예로 들어 고객이 결제한 상품 정보를 csv 파일로 저장하는 방법에 대해 알아볼 것이다.

관리자 사이트에 csv 파일로 저장할 수 있는 기능 추가

  • 경로 : order > admin.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    import csv # csv 파일 생성
    import datetime # created, updated - datetime객체인지 여부 확인을 위해, string으로 컨버팅
    from django.utils import timezone # 장고에서 사용하는 표준 시각을 반영하기 위핸 모듈
    from django.http import HttpResponse # 응답

    def export_to_csv(modeladmin, request, queryset):
    # modeladmin - modeladmin.model - 선택된 객체의 모델 정보
    # queryset : 선택된 객체
    opts = modeladmin.model._meta

    response = HttpResponse(content_type='text/csv')
    current_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S")
    # 파일 이름 설정
    response['Content-Disposition'] = f'attachment;filename={opts.verbose_name}-{current_time}.csv'
    writer = csv.writer(response)

    # 모델에서 필드 목록 불러와서 확인
    print(opts.get_fields())

    # 로컬 필드만을 리스트 형태로 fields 변수로 저장하기
    fields = [field for field in opts.get_fields() if not field.many_to_many and not field.one_to_many]
    # 로컬 필드명으로 헤더 만들기
    field_headers = [field.verbose_name for field in fields]
    field_headers += ['product name', 'quantity', 'Unit price', 'Total Price']
    # 로컬 필드명의 헤더를 행에 표시하기
    writer.writerow(field_headers)

    for obj in queryset:
    data_row = []
    # getattr(obj, 'items') : obj 객체에 'items'가 있으면 가져온다. (order_item 모델 정보 가져옴)
    order_items = getattr(obj, 'items').all()
    # 제품 마다 중복 출력될 주문 정보 만들기
    for field in fields:
    value = getattr(obj, field.name)
    # if isinstance(value, datetime.datetime) : value가 datetime.datetime 타입인 경우
    if isinstance(value, datetime.datetime):
    value = value.strftime("%Y-%m-%d")
    data_row.append(value)
    # 주문 정보와 함께 제품 정보 출력하기
    for order_item in order_items:
    # 주문 정보에 제품 정보를 껴넣기 위해 리스트 복제
    current_data = data_row.copy()
    current_data.append(order_item.product.name)
    current_data.append(order_item.quantity)
    current_data.append(order_item.price)
    current_data.append(order_item.get_item_total_price())
    writer.writerow(current_data)
    # 메모리 확보를 위해 리스트 삭제
    del(current_data)

    return response

    export_to_csv.short_description = "Oder Export to CSV"

참고) 결제 시, 고객이 입력해야 할 모델 및 주문 정보를 저장할 모델 설정

  • 경로 : order > models.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    from django.db import models
    from shop.models import Product

    # 결제 시, 고객이 입력해야 할 모델
    class Order(models.Model):
    # 결제 시도 전에 주문을 먼저 생성한다.
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.EmailField()

    address1 = models.CharField(max_length=100)
    address2 = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    postal_code = models.CharField(max_length=20)

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    paid = models.BooleanField(default=False)

    class Meta:
    ordering = ['-updated']

    def __str__(self):
    return f"Order {self.id}"

    # 고객이 주문한 정보를 저장할 모델
    class OrderItem(models.Model):
    # 주문 시스템을 구현할 때는 변동될 수 있는 정보는
    # 항상 별도로 복사해서 저장해둔다.
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.PROTECT, related_name='ordered_items')
    price = models.PositiveIntegerField()
    quantity = models.PositiveIntegerField(default=1)

    def __str__(self):
    return f"Order #{self.order.id} item {self.product.name}"

    def get_item_total_price(self):
    return self.price * self.quantity