> 백엔드 개발 > 파이썬 튜토리얼 > Python Django Framework 및 Htmx를 사용하여 단일 제품 상점 구축

Python Django Framework 및 Htmx를 사용하여 단일 제품 상점 구축

王林
풀어 주다: 2024-09-12 10:15:45
원래의
448명이 탐색했습니다.

Django, htmx, Stripe을 사용하여 단일 제품 전자상거래 웹사이트를 만드는 두 부분으로 구성된 시리즈 중 첫 번째입니다. 이 부분에서는 Django 프로젝트를 시작하고 이를 htmx와 통합하겠습니다.

2부에서는 Stripe로 주문을 처리해보겠습니다.

가자!

왜 Django, htmx, Stripe인가요?

다음과 같은 이유로 Django, htmx 및 Stripe를 사용하여 웹사이트를 만들 예정입니다.

  • Django는 훌륭한 ORM, 템플릿 및 라우팅 시스템을 갖춘 Python 웹 프레임워크입니다. 인증과 같은 즉시 사용할 수 있는 몇 가지 기능과 온라인에서 사용할 수 있는 여러 오픈 소스 패키지가 있습니다. 우리는 Django를 사용하여 웹사이트를 구축하겠습니다.
  • htmx는 html 속성을 사용하여 웹사이트에 현대적인 느낌을 주는 JavaScript 라이브러리입니다. 실제로 JavaScript를 작성할 필요는 없습니다(물론 가능하지만). 우리는 htmx를 사용하여 페이지에 약간의 상호 작용을 제공할 것입니다.
  • Stripe는 결제 및 신용카드 정보를 처리하는 훌륭한 API를 갖춘 결제 플랫폼입니다. 또한 Google 및 Apple Pay와도 잘 통합됩니다. 제품 결제를 용이하게 하기 위해 Stripe를 사용할 예정입니다.

최종 제품의 작동 방식은 다음과 같습니다.

  • 사용자가 당사 웹사이트를 방문하여 가격, 설명 등 당사 제품에 대한 일부 정보를 볼 수 있습니다.
  • 사용자가 '구매' 버튼을 클릭하면 Stripe의 결제 세션으로 리디렉션됩니다.
  • 결제가 성공하면 다시 당사 웹사이트로 리디렉션됩니다. 주문 정보를 저장하고 고객과 모든 직원에게 확인 이메일을 보내 최근 구매 사실을 알립니다.

이제 Django 프로젝트를 구성하고, 초기 보기를 생성하고, htmx로 구매 양식을 작성해 보겠습니다.

Django Python 프로젝트 구성

프로젝트를 설정하려면 가상 환경을 생성하고 활성화한 후 필요한 패키지를 설치해야 합니다. 그런 다음 Django 프로젝트와 Django 앱을 만들 수 있습니다.

가상 환경 생성

가상 환경을 만드는 것부터 시작하여 종속성을 분리해 보겠습니다.

python -m venv .venv
로그인 후 복사

Linux/Mac에서 활성화하는 방법은 다음과 같습니다.

source .venv/bin/activate
로그인 후 복사

Windows의 경우:

.venv\Scripts\activate
로그인 후 복사

필수 패키지 설치

활성화된 가상 환경 내에서 이 작업을 수행하려면 몇 가지 패키지가 필요합니다.

pip install django stripe django-htmx python-dotenv
로그인 후 복사

여기에는 다음이 설치되어 있습니다.

  • 장고
  • 스트라이프 API와 함께 작동하는 스트라이프.
  • django-htmx는 htmx 작업에 필요한 몇 가지 도우미 기능을 제공합니다.
  • .env 파일에서 환경 변수를 로드하는 python-dotenv.

Django 프로젝트 만들기

가상 환경과 동일한 디렉터리에 ecommerce_site라는 Django 프로젝트를 생성해 보겠습니다.

django-admin startproject ecommerce_site .
로그인 후 복사

Django에서는 하나 이상의 "앱"으로 코드를 구성하는 것이 좋습니다. 각 앱은 특정한 작업을 수행하는 패키지입니다. 프로젝트에는 여러 개의 앱이 있을 수 있지만 이 간단한 상점의 경우 전자 상거래 플랫폼의 보기, 양식 및 모델과 같은 대부분의 코드를 포함하는 하나의 앱만 있으면 됩니다. 이를 만들어 전자상거래라고 부르겠습니다.

python manage.py startapp ecommerce
로그인 후 복사

이 앱을 ecommerce_site/settings.py의 INSTALLED_APPS에 추가하세요.

# ecommerce_site/settings.py

INSTALLED_APPS = [
    # ... the default django apps
    "ecommerce", # ⬅️ new
]
로그인 후 복사

이 설정에 문제가 있는 경우 최종 제품을 확인하세요. 이 단계에서 파일 구조는 다음과 같아야 합니다.

ecommerce_site/
├── .venv/  # ⬅️ the virtual environment
├── ecommerce_site/ # ⬅️ the django project configuration
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── ecommerce/ # ⬅️ our app setup
│     ├── templates/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── manage.py
로그인 후 복사

템플릿 만들기

이제 프로젝트 구성이 완료되었으므로 기본 레이아웃을 생성해야 합니다. 템플릿 디렉토리에 다른 모든 템플릿이 상속받을 템플릿인 base.html 파일을 추가하세요. 사용자 상호 작용을 위한 htmx, 기본 스타일을 위한 mvp.css 및 Django 생성 메시지를 템플릿에 추가합니다.

<!-- ecommerce/templates/base.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>One-Product E-commerce Site</title>

    <!-- include htmx ⬇️ -->
    <script
      src="https://unpkg.com/htmx.org@1.9.11"
      integrity="sha384-0gxUXCCR8yv9FM2b+U3FDbsKthCI66oH5IA9fHppQq9DDMHuMauqq1ZHBpJxQ0J0"
      crossorigin="anonymous"
    ></script>

    <!-- include mvp.css ⬇️ -->
    <link rel="stylesheet" href="https://unpkg.com/mvp.css" />
  </head>
  <body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' hx-boost="true">
    <header>
      <h1>One-Product E-commerce Site</h1>
    </header>
    <main>
      <section>
        {% if messages %} {% for message in messages %}
        <p><mark>{{ message }}</mark></p>
        {% endfor %} {% endif %}
      </section>
      {% block content %} {% endblock %}
    </main>
  </body>
</html>
로그인 후 복사

동일한 templates 디렉토리에 홈 뷰용 home.html 템플릿을 만듭니다. base.html을 확장하고 해당 콘텐츠 섹션을 채워야 합니다.

<!-- ecommerce/templates/home.html -->

{% extends "base.html" %} {% block content %}
<section>{% include "product.html" %}</section>
{% endblock %}
로그인 후 복사

이 템플릿에는 product.html 템플릿이 포함되어 있습니다. product.html은 제품 및 자리 표시자 이미지에 대한 일부 세부정보를 렌더링합니다. 동일한 templates 디렉토리에 생성해 보겠습니다.

<!-- ecommerce/templates/product.html -->
<form>
  <img src="https://picsum.photos/id/30/400/250" alt="mug" />
  <h3>mug<sup>on sale!</sup></h3>
  <p>mugs are great - you can drink coffee on them!</p>
  <p><strong>5€</strong></p>
  <button type="submit" id="submit-btn">Buy</button>
</form>
로그인 후 복사

홈 뷰 생성

ecommerce/views.py에서 홈 템플릿을 렌더링할 뷰를 생성합니다.

# ecommerce/views.py

from django.shortcuts import render

def home(request):
    return render(request, 'home.html')
로그인 후 복사

ecommerce_site/urls.py의 urlpatterns에 추가하세요.

# ecommerce_site/urls.py

from django.contrib import admin
from django.urls import path
from ecommerce import views # ⬅️ new

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", views.home, name="home"), # ⬅️ new
]
로그인 후 복사

이제 다음을 사용하여 서버를 실행할 수 있습니다.

python manage.py runserver
로그인 후 복사

브라우저에서 http://127.0.0.1:8000으로 이동하면 다음과 같은 내용이 표시됩니다.

Build a One-Product Shop With the Python Django Framework and Htmx

It might feel like overkill to add a dedicated product.html template instead of just the product details in the home.html template, but product.html will be useful for the htmx integration.

Add the Form and Use Htmx

Great! We now have a view that looks good. However, it doesn’t do much yet. We'll add a form and set up the logic to process our product purchase. Here’s what we want to do:

  1. Allow the user to select how many products (mugs) they want to buy.
  2. When the user clicks “Buy”, make a POST request to a different view called purchase in the backend using hx-post.
  3. In that view, validate the form and wait for 2 seconds to simulate the Stripe integration (we'll cover this in the second part of this guide).
  4. Replace the form content with the purchase view response.
  5. While the order is processing, show a loading message and disable the “Buy” button, so that the user doesn’t accidentally make multiple orders.

Let's go step by step.

1: Add a Quantity Order Form

Let’s first create and add a simple order form to our view allowing a user to select the number of mugs they want. In ecommerce/forms.py, add the following code:

# ecommerce/forms.py

from django import forms

class OrderForm(forms.Form):
        quantity = forms.IntegerField(min_value=1, max_value=10, initial=1)
로그인 후 복사

In ecommerce/views.py, we can initialize the form in the home view:

# ecommerce/views.py

from ecommerce.forms import OrderForm # ⬅️ new

def home(request):
    form = OrderForm() # ⬅️ new - initialize the form
    return render(request, "home.html", {"form": form}) # ⬅️ new - pass the form to the template
로그인 후 복사

And render it in the template:

<!-- ecommerce/templates/product.html -->

<form method="post">
  <!-- Same product details as before, hidden for simplicity -->

  <!-- render the form fields ⬇️ -->
  {{ form }}

  <!-- the same submit button as before ⬇️ -->
  <button type="submit" id="submit-btn">Buy</button>
</form>
로그인 후 복사

2: Make a POST Request To a Different View

When the user clicks "Buy", we want to process the corresponding POST request in a dedicated view to separate the different logic of our application. We will use htmx to make this request. In the same ecommerce/templates/product.html template, let's extend the form attributes:

<!-- ecommerce/templates/product.html -->

<!-- add the hx-post html attribute ⬇️ -->
<form method="post" hx-post="{% url 'purchase' %}">
  <!-- Same product details as before, hidden for simplicity -->

  {{ form }}
  <button type="submit" id="submit-btn">Buy</button>
</form>
로그인 후 복사

With this attribute, htmx will make a POST request to the purchase endpoint and stop the page from reloading completely. Now we just need to add the endpoint.

3: Create the Purchase View

The purchase view can be relatively simple for now:

# ecommerce/views.py
import time # ⬅️ new

# new purchase POST request view ⬇️
@require_POST
def purchase(request):
    form = OrderForm(request.POST)
    if form.is_valid():
        quantity = form.cleaned_data["quantity"]
        # TODO - add stripe integration to process the order
        # for now, just wait for 2 seconds to simulate the processing
        time.sleep(2)
    return render(request, "product.html", {"form": form})
로그인 후 복사

In this view, we validate the form, extract the quantity from the cleaned data, and simulate Stripe order processing. In the end, we return the same template (product.html). We also need to add the view to the urlpatterns:

# ecommerce_site/urls.py

# ... same imports as before

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", views.home, name="home"),
    path("purchase", views.purchase, name="purchase"),  # ⬅️ new
]
로그인 후 복사

We now need to tell htmx what to do with this response.

4: Replace the Form Content With the Purchase View Response

Htmx has a hx-swap attribute which replaces targeted content on the current page with a request's response.
In our case, since the purchase view returns the same template, we want to swap its main element — the

:

<!-- ecommerce/templates/product.html -->

<!-- add the hx-swap html attribute ⬇️ -->
<form method="post" hx-post="{% url 'purchase' %}" hx-swap="outerHTML">
  <!-- Same product details as before, hidden for simplicity -->

  {{ form }}
  <button type="submit" id="submit-btn">Buy</button>
</form>
로그인 후 복사

The value outerHTML will replace the entire target element with the response from the purchase view. By default, the htmx target is the same element making the call — in our case, the element.

5: Tell Htmx What to Do When the Request Is Triggered

htmx provides some helper utilities for when a request is processing. In our case, we want to:

  • Disable the "Buy" button (to avoid a form re-submission) by using the hx-disabled-elt attribute.
  • Show a loading message on the screen by using the htmx-indicator class. This class changes its element's opacity when the request is triggered.
<!-- ecommerce/templates/product.html -->

<!-- add the hx-disabled-elt html attribute ⬇️ -->
<form
  method="post"
  hx-post="{% url 'purchase' %}"
  hx-swap="outerHTML"
  hx-disabled-elt="#submit-btn"
>
  <!-- Same product details as before, hidden for simplicity -->

  {{ form }}
  <button type="submit" id="submit-btn">Buy</button>

  <!-- add a loading message with the htmx-indicator class ⬇️ -->
  <p class="htmx-indicator"><small>Getting your mug ready...</small></p>
</form>
로그인 후 복사

Once the customer clicks the "Buy" button, htmx will disable that same button (identifiable by its submit-btn id), and show a loading message by changing the opacity of the p.htmx-indicator element.

The Result

Jump over to the browser.

You can see the final result in this GitHub repository.

It doesn’t do much else yet. But, if form validation fails, errors will display directly on the form, without the need to refresh the entire page. If the form succeeds, we will process the Stripe order accordingly. We'll see how to do this in the second part of this guide.

Wrapping Up

We've now set up the basics for our one-product ecommerce site. We've configured our Django project, integrated it with htmx to give our site some interactivity, and set up a basic order form for our product.

In the second part of this guide, we'll handle orders with Stripe, save the results in our database, and notify users after a successful purchase.

Until then, happy coding!

P.S. If you'd like to read Python posts as soon as they get off the press, subscribe to our Python Wizardry newsletter and never miss a single post!

위 내용은 Python Django Framework 및 Htmx를 사용하여 단일 제품 상점 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿