Django

⌘K
  1. Home
  2. Django
  3. Htmx
  4. beginner tutorial

beginner tutorial

স্টেপ ১: ভার্চুয়াল এনভায়রনমেন্ট তৈরি ও অ্যাক্টিভেট করুন (ঐচ্ছিক)

python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate     # Windows

স্টেপ ২: Django ও প্রয়োজনীয় লাইব্রেরি ইন্সটল করুন

pip install django django-htmx

স্টেপ ৩: প্রজেক্ট ও অ্যাপ তৈরি করুন

django-admin startproject htmx_dashboard
cd htmx_dashboard
python manage.py startapp products

স্টেপ ৪: টেইলউইন্ড সেটআপ করুন
বিকল্প ১: CDN ব্যবহার করুন (সরল উপায়)
base.html-এ সরাসরি টেইলউইন্ড CDN যোগ করুন 

স্টেপ ৫: settings.py কনফিগারেশন

# htmx_dashboard/settings.py

INSTALLED_APPS = [
    ...
    'products',
    'django_htmx',  # নতুন অ্যাপ যোগ করুন
]

MIDDLEWARE = [
    ...
    'django_htmx.middleware.HtmxMiddleware',  # HTMX মিডলওয়্যার
]

TEMPLATES = [
    {
        ...
        'DIRS': [BASE_DIR / 'templates'],  # টেমপ্লেট ডিরেক্টরি যোগ করুন
    }
]

প্রজেক্ট স্ট্রাকচার

htmx_dashboard/
├── htmx_dashboard/
   ├── __init__.py
   ├── settings.py
   ├── urls.py
   └── wsgi.py
├── products/
   ├── migrations/
   ├── __init__.py
   ├── admin.py
   ├── apps.py
   ├── forms.py
   ├── models.py
   ├── urls.py
   └── views.py
├── templates/
   ├── base.html
   └── products/
       ├── product_form.html
       ├── _product_form.html
       ├── product_list.html
       └── _product_list.html
├── venv/
├── manage.py
└── requirements.txt

৩. urls.py (প্রজেক্ট লেভেল)

# htmx_dashboard/urls.py
from django.contrib import admin
from django.urls import path, include

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

স্টেপ ৯: মডেল ও ফর্ম তৈরি করুন

# products/models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    description = models.TextField()

    def __str__(self):
        return self.name

# products/forms.py
from django import forms
from .models import Product

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'price', 'description']
        widgets = {
            'description': forms.Textarea(attrs={'rows': 3}),
        }

৬. products/views.py

from django.views.generic import CreateView, ListView
from django.urls import reverse_lazy
from django.http import HttpResponseBadRequest
from django.shortcuts import render
from .models import Product
from .forms import ProductForm

class ProductCreateView(CreateView):
    form_class = ProductForm
    template_name = "products/product_form.html"
    success_url = reverse_lazy("product_list")

    def get_template_names(self):
        if self.request.htmx:
            return ["products/_product_form.html"]
        return super().get_template_names()

    def form_valid(self, form):
        response = super().form_valid(form)
        if self.request.htmx:
            return render(self.request, "products/_product_list.html", {"products": Product.objects.all()})
        return response

    def form_invalid(self, form):
        if self.request.htmx:
            return HttpResponseBadRequest("Invalid form data")
        return super().form_invalid(form)

class ProductListView(ListView):
    model = Product
    context_object_name = "products"
    template_name = "products/product_list.html"

    def get_template_names(self):
        if self.request.htmx:
            return ["products/_product_list.html"]
        return super().get_template_names()

products/urls.py

from django.urls import path
from .views import ProductCreateView, ProductListView

urlpatterns = [
    path("create/", ProductCreateView.as_view(), name="product_create"),
    path("list/", ProductListView.as_view(), name="product_list"),
]

templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTMX Dashboard</title>
    <script src="https://unpkg.com/htmx.org@1.9.6"></script>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100">
    <div class="min-h-screen flex">
        <!-- Sidebar -->
        <aside class="w-64 bg-white shadow-lg fixed h-full">
            <div class="p-4">
                <h2 class="text-xl font-bold mb-4">Dashboard</h2>
                <nav>
                    <ul class="space-y-2">
                        <li>
                            <a hx-get="{% url 'product_create' %}" 
                               hx-target="#main-content"
                               hx-push-url="/products/create/"
                               class="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded">
                                Create Product
                            </a>
                        </li>
                        <li>
                            <a hx-get="{% url 'product_list' %}" 
                               hx-target="#main-content"
                               hx-push-url="/products/list/"
                               class="block px-4 py-2 text-gray-700 hover:bg-gray-100 rounded">
                                Product List
                            </a>
                        </li>
                    </ul>
                </nav>
            </div>
        </aside>

        <!-- Main Content -->
        <main class="flex-1 ml-64 p-8">
            <!-- Topbar -->
            <div class="bg-white shadow-sm rounded-lg p-4 mb-6">
                <div class="flex justify-between items-center">
                    <h1 class="text-2xl font-bold">{% block title %}{% endblock %}</h1>
                </div>
            </div>

            <!-- Dynamic Content -->
            <div id="main-content" class="bg-white rounded-lg shadow p-6">
                {% block content %}{% endblock %}
            </div>
        </main>
    </div>
</body>
</html>

templates/products/product_form.html

{% extends "base.html" %}

{% block title %}Create Product{% endblock %}

{% block content %}
    {% include "products/_product_form.html" %}
{% endblock %}

templates/products/_product_form.html

<div class="max-w-2xl mx-auto">
    <h2 class="text-2xl font-bold mb-4">Create Product</h2>
    <form method="POST" hx-post="{% url 'product_create' %}" hx-target="#main-content">
        {% csrf_token %}
        <div class="space-y-4">
            <div>
                <label class="block text-sm font-medium text-gray-700">Name</label>
                {{ form.name }}
            </div>
            <div>
                <label class="block text-sm font-medium text-gray-700">Price</label>
                {{ form.price }}
            </div>
            <div>
                <label class="block text-sm font-medium text-gray-700">Description</label>
                {{ form.description }}
            </div>
        </div>
        <button type="submit" class="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
            Submit
        </button>
    </form>
</div>

১১. templates/products/product_list.html

{% extends "base.html" %}

{% block title %}Product List{% endblock %}

{% block content %}
    {% include "products/_product_list.html" %}
{% endblock %}

templates/products/_product_list.html

<div class="overflow-x-auto">
    <table class="min-w-full divide-y divide-gray-200">
        <thead class="bg-gray-50">
            <tr>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Name</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Price</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Description</th>
            </tr>
        </thead>
        <tbody class="bg-white divide-y divide-gray-200">
            {% for product in products %}
            <tr>
                <td class="px-6 py-4 whitespace-nowrap">{{ product.name }}</td>
                <td class="px-6 py-4 whitespace-nowrap">${{ product.price }}</td>
                <td class="px-6 py-4 whitespace-nowrap">{{ product.description|truncatechars:50 }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>


মাইগ্রেশন ও রান সার্ভার



# ডাটাবেস মাইগ্রেট
python manage.py makemigrations
python manage.py migrate

# অ্যাডমিন ইউজার তৈরি (ঐচ্ছিক)
python manage.py createsuperuser

# সার্ভার রান
python manage.py runserver

টেস্ট করার স্টেপ

  1. http://localhost:8000/products/create/ এ গিয়ে ফর্ম পূরণ করুন
  2. সাবমিট করলে প্রোডাক্ট লিস্টে নতুন আইটেম যোগ হবে (HTMX এর মাধ্যমে)
  3. ব্রাউজার রিলোড করলে সম্পূর্ণ পেজ রেন্ডার হবে
  4. সাইডবারের লিংকগুলোতে ক্লিক করে HTMX ট্রানজিশন দেখুন

Key Features

  1. HTMX ইন্টিগ্রেশন:
    • পার্শিয়াল টেমপ্লেট লোডিং
    • URL সিনক্রোনাইজেশন (hx-push-url)
    • AJAX ফর্ম সাবমিশন
  2. টেইলউইন্ড ডিজাইন:
    • রেসপনসিভ ড্যাশবোর্ড
    • মডার্ন UI কম্পোনেন্ট
  3. ক্লাস-বেজড ভিউ:
    • CreateView এবং ListView এর এক্সটেন্ডেড ব্যবহার
    • ডাইনামিক টেমপ্লেট সিলেকশন

Articles

How can we help?