본문 바로가기
Django(웹서비스 만들기)

[8주차] 쇼핑몰 페이지 만들기

by SOHEE- 2022. 1. 15.

기존에 인스타그램 클론코딩했던 소스를 수정하여 쇼핑몰로 변경합니다. 

 

제품 상세 페이지 만들기

페이지 기본 구성 만들기

조금씩 수정하면서 수정된 내용을 바로 확인해볼 수 있도록 html, views.py, urls.py 모두 생성합니다.

1. templates > content 안에 ‘productdetail.html’ 파일을 생성하고, 부트스트랩 스타터를 복사하여 붙여넣어 기본적인 틀을 만들어 줍니다.

2. content > views.py 안에 위 html 페이지를 띄우는 로직을 만듭니다.

class ProductDetail(APIView):
    def get(self, request, pk):
        return render(request, 'content/productdetail.html')

3. urls.py 안에 path('product/', ProductDetail.as_view(), name='product')를 입력합니다.

4. 기본 페이지가 보이는지 웹으로 접속하여 확인 합니다. 

 

디테일 잡기

1. 네비게이션 바가 보여지게 main.html에서 해당 코드를 복사해 붙여 넣고, Head 안에 {% load static %} 도 입력합니다.

구글머티리얼아이콘은 <head>에, 네비게이션바는 <body>에 넣습니다.

 

2. 상품 이미지와 정보화면에 대한 코딩을 입력합니다.

<div style="display: flex; flex-direction: row; padding-top: 50px">
    <div style="width: 50%; height: 50%; margin:50px">
        <img style="width: 100%; height: 100%" src="{% get_media_prefix %}{{ product.image }}">
    </div>
    <div style="width: 50%; height: 50%; margin: 50px">
        <hr>
        <div style="font-size: 36px">
            {{ product.description }}
        </div>
        <hr>
        <div>
            <span style="margin-right: 100px;font-size: 24px"> 판매가 </span>
            <span style="font-size: 36px; color: red"> {{ product.price }} 원</span>
        </div>
        <hr>
        <div>
            <span style="margin-right: 80px;font-size: 24px"> 배송방법 </span>
            <span style="font-size: 20px"> 택배 </span>
        </div>
        <hr>
        <div>
            <span style="margin-right: 100px;font-size: 24px"> 배송비 </span>
            <span style="font-size: 20px"> 무료</span>
        </div>
        <hr>
        <div>
            <button type="button" class="btn btn-dark"> 바로 구매하기</button>
            <button type="button" class="btn btn-secondary"> 장바구니 담기</button>
            <button type="button" class="btn btn-secondary"> 관심상품등록</button>
        </div>
        <div style="margin-top: 100px;">
            <button type="button" class="btn btn-warning" style="width: 100%">카카오톡 공유하기</button>
        </div>
        <div style="margin-top: 5px">
            <button type="button" class="btn btn-success" style="width: 100%">네이버 공유하기</button>
        </div>
    </div>
</div>

 

3. 실제 제품 정보를 불러올 수 있도록 views.py의 내용을 수정합니다.

Product 테이블에 있는 정보 중 id가 1인 상품정보를 html에 전달합니다. 

class ProductDetail(APIView):
    def get(self, request):
        product = Product.objects.get(id=1)
        return render(request, 'content/productdetail.html', context=dict(product=product))

하드 코딩으로 넣은 제품의 정보가 아닌 메인에서 상품을 선택했을 때 해당 상품의 상세 페이지를 보여줄 수 있도록 상품 식별값을 pk로 받아오게 설정합니다.

class ProductDetail(APIView):
    def get(self, request, pk):
        product = Product.objects.get(id=pk)
        return render(request, 'content/productdetail.html', context=dict(product=product))

main.html에서 상품 이미지에 <a> 태그로 제품 상세페이지에 대한 링크를 설정합니다.

 

 

검색 만들기

네비게이션바의 검색창에서 특정 상품만을 검색할 수 있도록 수정합니다. 
상품 리스트가 나오는 과정을 조금만 수정하면 되는데, `Product.objects.all()`은 모든 상품을 전달하는 반면 `Product.objects.filter({키워드})`를 쓰면 키워드를 기준으로 테이블 내에서 정보를 걸러서 보여준다는 점을 활용합니다.

 

1. main.html에서 <from> 수정하기

네비게이션바 위치에서 Search 부분을 찾습니다. 
ajax처럼 <form>에서도 action으로 동작을 추가할 수 있는데, 검색할 때 ‘search’ 경로의 로직을 POST로 실행하도록 아래와 같이 추가하면서 입력한 검색어에 대해서는 keyword라는 이름을 지정합니다. 

<form action="{% url 'search' %}" method="post" class="d-flex">
    <input class="form-control me-2" type="search" name="keyword" placeholder="Search" aria-label="Search">
    <button class="btn btn-outline-success" type="submit">Search</button>
</form>

 

2. 메인 views.py에 있는 class Main을 복사하여 Search로 수정합니다.

class Search(APIView):
    def post(self, request):
        if request.session.get('login_check'):
            email = request.session.get('email')
            find_user = User.objects.filter(email=email).first()
            keyword = request.data.get('keyword')

            return render(request, 'learningspoons/main.html',
                          context=dict(
                              data_list=Product.objects.filter(description__contains=keyword).order_by('-id'),
                              user_info=find_user
                          ))
        else:
            return render(request, 'user/login.html')

 

3. urls.py에서 path('search/', Search.as_view(), name='search')를 입력합니다.

 

 

홈 로고 수정하기

로고를 누르면 메인 홈페이지로 이동할 수 있도록 href의 내용을 수정합니다.

href에 적혀있는 “#” 대신 “/” 혹은 “{% url ‘main’ %}”을 입력하여 메인 페이지 경로로 지정해줍니다. 

 

 

장바구니 만들기

장바구니 정보 테이블 만들기

models.py에서 장바구니 정보를 담을 cart 테이블을 아래와 같이 생성합니다.

상품정보나 가격을 장바구니 테이블에 중복저장하지 않고 product_id 값을 이용해 product 테이블에서 가져올 수 있도록 설정합니다.

 

class Cart(models.Model):
    email = models.TextField()
    product_id = models.IntegerField()
    count = models.IntegerField()

    class Meta:
        unique_together = ('email', 'product_id')

 

장바구니에 담기 버튼 동작 만들기

productdetail.html에서 [장바구니 담기] 버튼을 눌렀을 때, 해당 상품의 product_id를 뒤에 만들 AddCart 로직으로 전송할 수 있도록 ajax를 작성합니다.

$('#add_cart').click(function () {
    $.ajax({
        url: {% url 'addcart' %},
        method: 'POST',
        data: {
            product_id: {{ product.id }}
        },
        success: function (data) {
            alert('장바구니에 추가되었습니다.')
        },
        error: function (request, status, error) {
            alert('장바구니에 추가 실패')
        },
    })
})

 

장바구니에 데이터 저장하는 로직 만들기

views.py에서 상품 정보를 Cart 테이블에 저장하는 로직을 작성합니다.

class AddCart(APIView):
    def post(self, request):
        email = request.session.get('email')    # 세션에서 email값 가져오기
        product_id = request.data.get('product_id') # 인풋에서 product_id값 가져오기

        if Cart.objects.filter(email=email, product_id=product_id).exists():
            # 만약 장바구니에 같은 상품이 있으면 더하기
            cart_in_db = Cart.objects.filter(email=email, product_id=product_id).first()
            cart_in_db.count = cart_in_db.count + 1
            cart_in_db.save()
        else:
            # 장바구니에 같은 상품이 없으면 생성
            Cart.objects.create(email=email, product_id=product_id, count=1)

        return Response(status=200)

urls.py에서 path('addcart/', AddCart.as_view(), name='addcart')를 추가합니다.

 

장바구니 화면 만들기

cart.html을 새로 만들어서 장바구니 테이블에 담긴 정보를 표시할 화면을 구성합니다.

<div style="display: flex; flex-direction: row;">
    <div style="width: 200px;text-align: center">상품 이미지</div>
    <div style="width: 500px;text-align: center">상품정보</div>
    <div style="width: 200px;text-align: center">가격</div>
    <div style="width: 50px;text-align: center">수량</div>
</div>

 

views.py에 사용자의 장바구니 아이템을 내려주는 코드를 작성합니다.

class CartView(APIView):
    def get(self, request):
        email = request.session.get('email')    # 세션에서 email값 가져오기

        cart_item_list = Cart.objects.filter(email=email)   # 로그인한 사용자의 장바구니 아이템 전부 가져오기

        data_list = []  # 빈 리스트 생성

        for cart_item in cart_item_list:
            # 사용자의 카트 아이템들을 하나씩 보면서 상품정보를 불러옴
            product = Product.objects.get(id=cart_item.product_id)

            # data_list에 하나씩 추가
            data_list.append(dict(
                product=product,
                count=cart_item.count
            ))

        return render(request, 'content/cart.html', context=dict(data_list=data_list))

 

views.py에서 넘어온 데이터를 for문으로 하나씩 출력하는 코드를 cart.html에 추가로 작성합니다.

{% for data in data_list %}
    <div style="display: flex; flex-direction: row;">
        <div style="width: 200px"><img width="150px" src="{% get_media_prefix %}{{ data.product.image }}"></div>
        <div style="width: 500px">
            <div> {{ data.product.seller }}</div>
            <div style="font-size: 24px"> {{ data.product.description }}</div>
        </div>
        <div style="width: 200px;font-size: 24px; color: red">{{ data.product.price }} 원 </div>
        <div style="width: 50px;text-align: center">{{ data.count }}</div>
    </div>
    <hr>
{% endfor %}

 

이것저것 장바구니에 넣어 출력되는 화면을 확인합니다.

 

'Django(웹서비스 만들기)' 카테고리의 다른 글

[10주차] 프로젝트-2  (0) 2022.01.30
[9주차] 프로젝트-1  (0) 2022.01.15
[7주차] 여러 서비스 연계하기  (0) 2022.01.08
[6주차] AWS에 웹 서비스 배포하기  (0) 2021.12.29
[5주차] Git 사용하기  (0) 2021.12.24