본문 바로가기
코딩 연습/코딩배우기

파이썬 장고(django) 웹 프로그래밍 - 웹 페이지 만들기 # 2

by good4me 2021. 11. 3.

goodthings4me.tistory.com

 

파이썬 장고(django) 웹 프로그래밍 - 웹 페이지 만들기 (2)

 

12. products 앱 생성 

- 상품 등록과 관리를 위한 products 앱 생성하기

(venv) PS D:\borame> python manage.py startapp products

 

- 앱 등록하기 : settings.py 에 'products' 추가

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts',
    'products',
]

 

- config>urls.py 에 경로 설정에 products 경로 추가

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accounts.urls')),
    path('', include('products.urls')),
]

 

- products 앱에 templates 폴더를 만들고 그 하위에 products 폴더를 만든다.

* products>templates>products

 

- products>urls.py 파일 생성, path 지정

* app_name도 지정하고 views.py import 함

from django.urls import path
from . import views

app_name = 'products'

urlpatterns = [
    path('', views.index, name='index'),
]

 

good4me.co.kr

 

 

- views.py 에 index() 작성

from django.shortcuts import render

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

 

- localhost:8000으로 접속 시 index.html로 연결되도록 템플릿 파일 작성

* products>templates>products>index.html

{% extends 'base.html' %}
{% block content %}
<br>
<h3>Products Page</h3>

{% endblock %}

 

- base.html의 Home에 URL 지정

<li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li> 부분을

<li class="nav-item"><a class="nav-link active" aria-current="page" href="{% url 'products:index' %}">Home</a></li> 로 수정

* Home 클릭 시, products 앱에서 name이 index 인 path URL로 보내고, views.py의 index() 함수가 처리함

 

- localhost:8000 접속 시, 아래 이미지가 보임(Home 클릭 시 또는 로그인/로그아웃 후에도 동일)

 

- base.html의 Home에 URL 지정

 

 

13. 쿠팡 파트너스 API 데이터 등록을 위한 products 앱 모델(models) - db 작성

※ 개인적으로 구상한 db 임

  • 적용할 사이트명(스마트스토어, 쿠팡, 쿠팡API)은 선택(Select) 리스트로 처리
  • 상품카테고리(코드와 이름)도 통일성과 오타 등의 오류 방지를 위해 Foreign Key로 db 적용
  • 상품카테고리는 추가 가능하나 쿠팡의 분류를 default로 함 

 

- products models.py 

from django.db import models


class Product(models.Model):
    SITE_NAME = (
        ('smartstore', 'Smartstore'),
        ('coupang', 'Coupang'),
        ('coupapi', 'Coupang API'),
    )

    site_name = models.CharField(max_length=100, verbose_name='상품 사이트명', choices=SITE_NAME)
    product_name = models.CharField(max_length=200, verbose_name='상품명', help_text='상품 상세페이지의 상품 제목')
    product_url = models.CharField(max_length=1000, verbose_name='상품 Link URL', help_text='상품 상세페이지 URL Copy & Paste')
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    product_image = models.CharField(max_length=1000, verbose_name='상품이미지 Link URL')
    product_no = models.CharField(max_length=30, verbose_name='상품번호(코드)', help_text='상품 각각의 고유번호')
    view_ox = models.BooleanField(verbose_name='사용자에게 보여주기', default=True, help_text=' (체크 시 보여줌)')
    hits = models.PositiveIntegerField(default=0, verbose_name='클릭 카운트')
    updated = models.DateTimeField(auto_now=True)
    product_rank = models.IntegerField(verbose_name='랭크', null=True, blank=True)
    product_content = models.TextField(verbose_name='상품내용(요약)', null=True, blank=True)
    etc1 = models.CharField(max_length=1000, verbose_name='비고1', null=True, blank=True)
    etc2 = models.CharField(max_length=1000, verbose_name='비고2', null=True, blank=True)

    def __str__(self):
        return self.product_name

    @property
    def click_counter(self):
        self.hits += 1
        self.save()


class Category(models.Model):
    categ_code = models.CharField(max_length=10, verbose_name='카테고리 코드')
    categ_name = models.CharField(max_length=200, verbose_name='카테고리 분류 명칭')

    def __str__(self):
        return f'{self.categ_code} - {self.categ_name}'

* category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True) 처럼 외래키(Foraign key) 지정 시 db 테이블에서는 category_id로 표시됨

* table명은 products_product 처럼 "앱이름_모델명"으로 됨

 

- models 마이그레이션 및 마이그레이트

(venv) PS D:\borame> python manage.py makemigrations products
Migrations for 'products':
  products\migrations\0001_initial.py
    - Create model Category
    - Create model Product
(venv) PS D:\borame> python manage.py migrate products
Operations to perform:
  Apply all migrations: products
Running migrations:
  Applying products.0001_initial... OK
(venv) PS D:\borame>

 

* DB Browser for SQLite 설치하여 db 관리 (2개의 테이블 생성 확인)

 

 

- admin에 앱 등록

from django.contrib import admin
from .models import Product, Category


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ['id', 'category', 'site_name', 'product_name', 'view_ox', 'hits', 'updated']
    list_display_links = ['id', 'site_name', 'product_name']
    list_per_page = 30


@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ['id', 'categ_code', 'categ_name']
    list_display_links = ['id', 'categ_code', 'categ_name']

 

 

- admin 에 로그인 후 테스트 데이터 입력

admin 로그인 후 Products 클릭

 

 

ADD PRODUCT 클릭

 

 

카테고리 입력

 

 

14. index.html에서 입력 데이터 보이기

- views.py 수정
. index.html에서 등록 상품을 보여줄 때 카테고리 코드에 따라 보여주도록 할 것이며,
. default는 일단 category_code 1001로 하고, 
. 카테고리 선택 시 해당 카테고리 상품이 보이도록 한다.
l. ocalhost:8000 접속 시 code 1001을 db에서 추출하여 템플릿에 전달하도록 index() 수정

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


def index(request):
    category = Category.objects.get(categ_code='1001')
    product_list = Product.objects.all().filter(category_id=category.id).order_by('-id')
    context = {'product_list': product_list}
    return render(request, 'products/index.html', context)

. 카테고리 코드가 1001인 상품을 Product 모델에서 Queryset으로 가져오고 index.html 템플릿에 전달함

. Product.objects.filter 의 filter() 는 sql query의 where 절에 해당

 

- index.html 수정

{% extends 'base.html' %}
{% block content %}

{% if product_list %}
<div class="container">
    <div class="row" style="padding: 2px 0px">
    {% for prd in product_list %}
        {% if prd.view_ox %}
        <div class="col p-3 border bg-light">
            <p style="text-align:center;"><a href="{{ prd.product_url }}" target="_blank">
                <img src="{{ prd.product_image }}" width="250"></a></p>
            <p><h4><a href="{{ prd.product_url }}" target="_blank">{{ prd.product_name }}</a></h4></p>
            <p><small style="color:silver">등록(수정): {{ prd.updated|date:"Y-m-d H:i:s" }}</small></p>
        </div>
        {% endif %}
    {% endfor %}
    </div>
</div>

{% else %}
<div class="row">
    <div class="col-md-12 panel panel-default">
        <p>표시할 목록이 없습니다.</p>
    </div>
</div>

{% endif%}

{% endblock %}

 

 

댓글