6 분 소요

Basic templates, URL’s and VIews (4)

/ get_object_or_404 / templates - settings.py / 장고 Templates 설정

Building the Category View

  • 현재 카테고리에는 Jacket, Pants, Top 이렇게 3개의 항목이 있는데 이 부분을 연결시켜주려면 이전에 했던 작업에서 뷰를 연결시켜주면 된다.
  • Populate data 이걸 한국에서 정확히 뭐라고 옮겨서 말하는지 모르겠다 Annotation도 어노테이션 애노테이션 애너테이션 등등 제각각이다.
  • 그렇다고 영어 표기로된 것도 아님..
  • Populate data
    • to automatically add information to a list or table on a computer: There are several ways to populate the database. SMART Vocabulary: related words and phrases. Environmental issues. agroecology.

ecommerce>store>views.py

from django.shortcuts import render
from .models import Category

def store(request):
    return render(request, 'store/store.html')

def categories(request):
    all_categories = Category.objects.all()
    return {'all_categories': all_categories} # key/value
  • 모델 카테고리의 모든 객체를 불러와서 키값과 벨류값으로 리턴해준다.

    settings.py

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                   'django.template.context_processors.debug',
                  'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                    'store.views.categories',
                ],
            },
        },
    ]
    
  • settings.py 에서 뷰의 categories를 등록해준다.
  • This is a context processor that we’re adding.
  • It’ll allow it to be available our data on every single template or page s owe can reference this easily
  • templates 참고 : https://query.tistory.com/entry/%EC%9E%A5%EA%B3%A0-settingspy-%ED%85%9C%ED%94%8C%EB%A6%BF-%ED%8F%B4%EB%8D%94-%EC%9C%84%EC%B9%98-%EC%A7%80%EC%A0%95-%EB%B0%A9%EB%B2%95
  • 상품요약페이지든 장바구니든 모든 페이지에서 해당 기능을 사용하기위해 등록해준다고 이해하면 됨

장고 Templates 설정

  • 장고에서 template는 MVC 패턴에서 view와 비슷한 기능을 한다.
  • templates는 데이터를 사용자에게 보여주는 컴포넌트다.
  • 이러한 template의 경로나 정보를 설정하는 곳이 TEMPLATES다.
  • 기본 설정은 앱 디렉토리 내에 ‘templates’ 디렉토리를 각각 생성해서 괸리하도록 구성되어 있으며, 이에 따라 위의 View에서 반환되는 템플릿 파일 경로는 다음과 같다
  • 참고 : https://velog.io/@ansalstmd/Django-Template-%EA%B8%B0%EB%8A%A5

여러개의 templates 관리

참고: https://hwan-hobby.tistory.com/126

ecommerce>store>templates>store>base.html

<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
	<li>
		<a class="dropdown-item" href="{% url 'store' %}"> All </a>
	</li>
	
	{% for category in all_categories %}
	<li>
		<a class="dropdown-item" href="">{{ category.name }}</a>
	</li>
	{% endfor %}
	
</ul>
  • Jinja랑 비슷하다고 생각했는데 Jinja 맞다 ㅋ
  • 템플릿 엔진 사용법은 대부분 비슷비슷하다.
  • 키 값으로 받은 all_categories 를 루프로 돌려서 나열해 출력해주면 된다.
  • 부트스트랩 테마에서 자동으로 첫 글자가 대문자라서 상관없지만 해당 설정이 없는 경우 `` 를 사용해서 처리해줄 수도 있다.
    • 필요한 사항이 있으면 https://jinja.palletsprojects.com/en/3.1.x/ 여기서 확인하면 된다

Styling the main product data grid

  • 메인화면에 그리드 형태로 상품나열 꾸미기

ecommerce>store>views.py

from django.shortcuts import render
from .models import Category,Product

def store(request):
    all_products = Product.objects.all()
    context = {'my_products':all_products}
    return render(request, 'store/store.html',context)

def categories(request):
    all_categories = Category.objects.all()
    return {'all_categories': all_categories} # key/value

ecommerce>store>templates>store>store.html

   <!-- All products section -->
   <div class="album py-5 bg-light">
    <div class="container">
      <div class="pb-3 h5"> All products </div>
      <hr>
      <br>
      <div class="row row-cols-1 row-cols-sm-2 row-cols-md-5 g-3">
        {% for product in my_products %}
          <div class="col">
            <div class="card shadow-sm">
              <img class="img-fluid" alt="Responsive image" src="{{product.image.url}}">
              <div class="card-body">
                <p class="card-text">
                  <a class="text-info text-decoration-none" href="{{product.get_absolute_url}}">{{product.title | capfirst}}</a>
                </p>
                <div class="d-flex justify-content-between align-items-center">
                  <h5>
                    
                    {{product.price}}
                  </h5>
                </div>
              </div>
            </div>
          </div>
        {% endfor %}
      </div>
    </div>
  </div>
  • 뭔가 복잡하지만 처음에 카테고리를 루프로 돌린거랑 원리는 똑같다.
  • 카드형식의 테마도 부트스트랩에서 취향껏 선탠해서 조정하면 됨

Creating the singular product page

  • 상품을 클릭하면 해당 상품에 대한 싱글 페이지를 만들기

ecommerce>store>urls.py

from django.urls import path
from . import views

urlpatterns = [
    # Store main page
    path('', views.store, name='store'),
    # Individual product
    path('product/<str:product_slug>/', views.product_info, name='product-info'),
]
  • slug 가 현재 한글로 되어 있어서 범용성을 위해 str로 변경
  • 슬러그를 통한 고유링크가 product_info 랑 연결되고 URL 매핑에 name 속성 부여 -> ‘product-info’
  • 참고 : https://wikidocs.net/70741

ecommerce>store>views.py

from django.shortcuts import get_object_or_404

def product_info(request, product_slug):
    product = get_object_or_404(Product, slug=product_slug)
    context = {'product': product }
    return render(request, 'store/product-info.html', context)
  • get_object_or_404 는 모델 Product에서 slug가 파라미터 product_slug로 받은 값과 일치하는걸 갖고 온다.
  • 갖고 온 값을 context 의 value 값에 넣음
  • context = context 라고 해도 되고 그냥 context라고 해도 된다 (자리 순서만 맞으면 됨)

ecommerce>store>templates>store>product-info.html

<img class="img-fluid mx-auto d-block" alt="Responsive image" src="">




  • 키값 product에서 갖고 올 때 이미지는 static 폴더에 있으니 .url 까지 써줘야한다.

  • 이제 메인 페이지에서 해당 상품을 클릭하면 그 페이지로 넘어가게 설정을 해보자

ecommerce>store>models.py

class Category(models.Model):
    def get_absolute_url(self):
        return reverse("list-category", args=[self.slug])
        
class Product(models.Model):
    def get_absolute_url(self):
        return reverse("product-info", args=[self.slug])
  • 클래스 Category, Product 에 get_absolute_url 함수를 선언해준다.
  • urls.py 에서 path에 name으로 지정한 product-info으로 url을 연결해준다.

ecommerce>store>templates>store>store.html

<p class="card-text">
	<a class="text-info text-decoration-none" href="">
		
	</a>
</p>
  • 키값 product에서 함수 get_absolute_url 를 불러온 값이 싱글페이지 주소랑 같으므로 해당 상품의 페이지로 연결된다.

Building the list category view

  • 이쪽 카테고리도 연결시켜보자

ecommerce>store>urls.py

from django.urls import path
from . import views
urlpatterns = [
    # Store main page
    path('', views.store, name='store'),
    
    # Individual product
    path('product/<str:product_slug>/', views.product_info, name='product-info'),

    # Individual category
    path('search/<str:category_slug>/', views.list_category, name='list-category'),
]
  • 이전과 같은 원리다.

ecommerce>store>views.py

def list_category(requst, category_slug = None):
    category = get_object_or_404(Category, slug=category_slug)
    products = Product.objects.filter(category = category)
    return render(requst, 'store/list-category.html', {'category': category, 'products':products})
  • 카테고리와 맞는 상품들만 객체로 옮김

ecommerce>store>models.py

class Category(models.Model):
    def get_absolute_url(self):
        return reverse("list-category", args=[self.slug])

ecommerce>store>templates>store>base.html

{% for category in all_categories %}
<li>
	<a class="dropdown-item" href="{{category.get_absolute_url}}">
	{{ category.name }}
	</a>
</li>
{% endfor %}

ecommerce>store>templates>store>list-category.html

{% extends "./base.html" %}
{% load static %}
{% block content %}
  <main>
    <div class="album py-5 bg-light">
      <div class="container">
        <div class="pb-3 h5">{{category.name | capfirst}}
          <!-- category.name -->
        </div>
        <hr>
        <br>
        <div class="row row-cols-1 row-cols-sm-2 row-cols-md-5 g-3">
          <!-- for product in products -->
          {% for product in products %}
            <div class="col">
              <div class="card shadow-sm">
                <img class="img-fluid" alt="Responsive image" src="{{product.image.url}}">
                <div class="card-body">
                  <p class="card-text">
                    <a class="text-info text-decoration-none" href="{{product.get_absolute_url}}">
                      {{product.title}}
                      <!-- product title -->
                    </a>
                  </p>
                  <div class="d-flex justify-content-between align-items-center">
                    <h5>
                      
                      {{product.price}}
                      <!-- product price -->
                    </h5>
                  </div>
                </div>
              </div>
            </div>
          {% endfor %}
        </div>
      </div>
    </div>
  </main>
{% endblock %}
  • 필터링 된 상품들만 루프를 돌면서 보내준다.

댓글남기기