django1

 

  • আমি windows 10 use করি।এখন আমি আমার desktop এ djnagosite নামে একটা ফোল্ডার এ তোমার ইচ্ছামত নাম দিয়ে একটা ৩ পেইজের ওয়েবসাইট বানিয়ে দাও। আমি windows powershell and vs code editor ইউজ করতে চাই। একেবারে শূন্য থেকে খুব ভালো করে সহজ করে শিখিয়ে দাও কোডের ব্যাখ্যা সহ ।আমার লক্ষ্য django দিয়ে যেকোনো এডুকেশন ওয়েবসাইট এবং ই কমার্স যেন বানাতে পারি,এখন শুরু করো। কোন ভুল করবে না। একেবারে সঠিক তথ্য ও কোড দিবে যেন ভবিষ্যতে vps এ সাইট বানাতে পারি djnago দিয়ে

  • 🧠
    Claude Opus 5

    Django দিয়ে প্রথম ৩-পেইজ ওয়েবসাইট (শূন্য থেকে) — Windows 10 + PowerShell + VS Code

    আমি সাইটের নাম দিলাম: ShikkhaBazar (শিক্ষা + বাজার) — কারণ আপনার লক্ষ্য একদিকে এডুকেশন সাইট, অন্যদিকে ই-কমার্স। তাই এই একটা প্রজেক্টেই দুটোর ভিত্তি (Course model + Price + Admin + Form + Media/Image) শিখে ফেলবেন।

    যে ৩টি পেইজ বানাব: Home (হোম), Courses (কোর্স/প্রোডাক্ট লিস্ট), Contact (যোগাযোগ ফর্ম — ডেটাবেজে সেভ হবে)।


    ০. আগে বুঝে নিন: Django আসলে কীভাবে কাজ করে

    Django হলো Python-এর একটা web framework — মানে রেডিমেড যন্ত্রপাতি সহ কারখানা। এটি MTV প্যাটার্ন ফলো করে:

    অংশমানেকাজফাইল
    M – Modelডেটার গঠনডেটাবেজ টেবিল (কোর্স, প্রোডাক্ট, অর্ডার)models.py
    T – TemplateচেহারাHTML পেইজtemplates/*.html
    V – Viewলজিকরিকোয়েস্ট নেয়, ডেটা আনে, টেমপ্লেট রিটার্ন করেviews.py
    URLconfরাউটারকোন লিংকে কোন view চলবেurls.py

    একটা রিকোয়েস্টের যাত্রাপথ:

    ব্রাউজার/courses/urls.pyরাউটিংviews.pyলজিকmodels.pyডেটাবেজtemplatecourses.htmlব্রাউজারেHTML পেইজ

    এই ছবিটা মাথায় গেঁথে নিন — Django-র ৯০% কাজ এই ৪টা ফাইলেই।


    ১. কোন ভার্সন ইনস্টল করব? (২০২৬ সালের সঠিক তথ্য)

    সফটওয়্যারযা ব্যবহার করবেনকেন
    Python3.13.x (3.12–3.14 চলবে)সব প্যাকেজের সাপোর্ট আছে
    Django5.2 LTSLTS = Long Term Support, সিকিউরিটি আপডেট এপ্রিল ২০২৮ পর্যন্ত। VPS/প্রোডাকশনের জন্য আদর্শ
    (বিকল্প)Django 6.1সর্বশেষ ভার্সন (আগস্ট ২০২৬), কিন্তু সাপোর্ট উইন্ডো ছোট
    EditorVS Codeফ্রি ও সেরা
    DatabaseSQLite (শেখার সময়) → PostgreSQL (VPS-এ)Django-তে ডিফল্ট SQLite, কনফিগ ছাড়াই চলে

    🔒 ছোট নোট: Windows 10-এর অফিসিয়াল সাপোর্ট ২০২৫ সালের অক্টোবরে শেষ হয়েছে। শেখার জন্য কোনো সমস্যা নেই, তবে ভবিষ্যতে Windows 11-এ যাওয়ার পরিকল্পনা রাখুন।

    ১.১ Python ইনস্টল

    1. python.org/downloads → Windows installer (64-bit) ডাউনলোড করুন (Python 3.13.x)।
    2. ইনস্টলারে অবশ্যই ☑️ Add python.exe to PATH টিক দিন → Install Now।

    ১.২ VS Code ইনস্টল

    code.visualstudio.com থেকে ইনস্টল করে এই এক্সটেনশনগুলো নিন:

    এক্সটেনশনকাজ
    Python (Microsoft)কোড রান, IntelliSense, ডিবাগ
    Pylanceদ্রুত অটো-কমপ্লিট
    Django (Baptiste Darthenay){% %} ট্যাগে কালার ও স্নিপেট

    ২. PowerShell খুলে প্রস্তুতি

    Start menu → powershell লিখে Windows PowerShell খুলুন। প্রথমে চেক করুন:

    powershell

    py --version pip --version

    Python 3.13.x দেখালে ঠিক আছে। (না দেখালে PC রিস্টার্ট দিন — PATH আপডেট হবে।)

    ২.১ একটি জরুরি সেটিং (এটা না করলে পরে আটকে যাবেন)

    PowerShell ডিফল্টভাবে স্ক্রিপ্ট চালাতে দেয় না, ফলে virtual environment চালু হয় না। একবার এই কমান্ডটি দিন:

    powershell

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

    Y চাপুন। এটি শুধু আপনার ইউজারের জন্য, নিরাপদ।

    ⚠️ PowerShell টিপস: পুরনো Windows PowerShell 5.1-এ && কাজ করে না। দুটো কমান্ড একসাথে দিতে ; ব্যবহার করুন, নাহয় আলাদা আলাদা লাইনে দিন।


    ৩. ফোল্ডার তৈরি ও ভার্চুয়াল এনভায়রনমেন্ট

    powershell

    cd $HOME\Desktop mkdir djnagosite cd djnagosite

    এখন virtual environment (venv) বানান:

    powershell

    py -m venv venv

    venv কী? এটা একটা আলাদা বক্স, যেখানে শুধু এই প্রজেক্টের প্যাকেজ (Django ইত্যাদি) থাকবে। ফলে অন্য প্রজেক্টে অন্য ভার্সন ব্যবহার করতে পারবেন, কোনো সংঘর্ষ হবে না। প্রফেশনাল কাজে venv ছাড়া কেউ কাজ করে না।

    চালু (activate) করুন:

    powershell

    .\venv\Scripts\Activate.ps1

    সফল হলে লাইনের শুরুতে দেখবেন:

    (venv) PS C:\Users\YourName\Desktop\djnagosite>

    বন্ধ করতে চাইলে: deactivate। কম্পিউটার বন্ধ করে আবার কাজ শুরু করলে প্রতিবার উপরের activate কমান্ডটি দিতে হবে — এটাই সবচেয়ে বেশি ভুলে যাওয়া ধাপ।


    ৪. Django ইনস্টল

    powershell

    python -m pip install --upgrade pip pip install "Django==5.2.*"

    চেক করুন:

    powershell

    python -m django --version

    আউটপুট: 5.2.x ✅


    ৫. প্রজেক্ট তৈরি (খেয়াল করুন শেষের ডট .)

    powershell

    django-admin startproject shikkhabazar .

    শেষের . মানে: "এখানেই বানাও, বাড়তি ফোল্ডার বানিও না"। এটা না দিলে djnagosite\shikkhabazar\shikkhabazar\... এভাবে ডাবল ফোল্ডার হয়ে বিভ্রান্তি তৈরি করে।

    VS Code-এ খুলুন:

    powershell

    code .

    ৫.১ VS Code-এ Python interpreter সিলেক্ট করুন (গুরুত্বপূর্ণ)

    Ctrl + Shift + P → লিখুন Python: Select Interpreter → যেটার নামে ('venv': venv) লেখা আছে সেটি বাছুন। এতে VS Code-এর ভেতরের টার্মিনালও অটো-activate হবে এবং import-এ লাল দাগ পড়বে না।

    ৫.২ এখন যেসব ফাইল তৈরি হয়েছে — প্রতিটির ব্যাখ্যা

    djnagosite/ ├── venv/ ← ভার্চুয়াল এনভায়রনমেন্ট (কখনো এডিট করবেন না, GitHub-এ দেবেন না) ├── manage.py ← প্রজেক্ট চালানোর রিমোট কন্ট্রোল └── shikkhabazar/ ← প্রজেক্টের "মগজ" (কনফিগারেশন) ├── __init__.py ← এটি ফোল্ডারটিকে Python প্যাকেজ বানায় (খালি ফাইল) ├── settings.py ← সব সেটিং: অ্যাপ লিস্ট, ডেটাবেজ, টেমপ্লেট, static ├── urls.py ← মেইন রাউটার (কোন লিংক কোথায় যাবে) ├── asgi.py ← async সার্ভারে (Daphne/Uvicorn) চালানোর ঢোকার দরজা └── wsgi.py ← VPS-এ Gunicorn এই ফাইল দিয়েই সাইট চালাবে

    ৫.৩ প্রথম রান

    powershell

    python manage.py migrate python manage.py runserver
    • migrate = Django-র বিল্ট-ইন টেবিলগুলো (ইউজার, সেশন, অ্যাডমিন লগ) ডেটাবেজে বানিয়ে দেয় → db.sqlite3 ফাইল তৈরি হবে।
    • runserver = ডেভেলপমেন্ট সার্ভার চালু করে।

    ব্রাউজারে যান 👉 http://127.0.0.1:8000/ — রকেটের ছবিসহ "The install worked successfully!" দেখলে অভিনন্দন! 🎉

    সার্ভার বন্ধ করতে টার্মিনালে Ctrl + C।


    ৬. অ্যাপ (app) তৈরি

    Django-তে প্রজেক্ট = পুরো সাইট, অ্যাপ = সাইটের একটা বিভাগ। ভবিষ্যতে ই-কমার্সে আপনার থাকবে products, cart, orders — আলাদা আলাদা অ্যাপ।

    নতুন টার্মিনাল ট্যাবে (বা Ctrl+C দিয়ে সার্ভার থামিয়ে):

    powershell

    python manage.py startapp pages

    ৬.১ অ্যাপের ফাইলগুলোর কাজ

    ফাইলকাজ
    models.pyডেটাবেজ টেবিলের ডিজাইন
    views.pyপেইজের লজিক
    admin.pyঅ্যাডমিন প্যানেলে কোন model দেখাবে
    apps.pyঅ্যাপের কনফিগ (হাত দিতে হয় না)
    tests.pyঅটোমেটেড টেস্ট
    migrations/model পরিবর্তনের ইতিহাস
    urls.pyনেই — আমরা নিজে বানাব

    ৭. settings.py সেটআপ (লাইন ধরে ব্যাখ্যা)

    shikkhabazar/settings.py খুলে নিচের অংশগুলো খুঁজে এভাবে বদলান:

    ৭.১ অ্যাপ রেজিস্টার

    python

    INSTALLED_APPS = [ "django.contrib.admin", # অ্যাডমিন প্যানেল "django.contrib.auth", # লগইন/ইউজার সিস্টেম "django.contrib.contenttypes", "django.contrib.sessions", # সেশন (কার্টের জন্য দরকার হবে) "django.contrib.messages", # সাকসেস/এরর মেসেজ দেখানো "django.contrib.staticfiles", # CSS/JS/Image হ্যান্ডলিং # আমার নিজের অ্যাপ "pages", ]

    👉 নতুন অ্যাপ বানালে এখানে নাম না লিখলে Django সেটি চিনবে না — নতুনদের #১ ভুল।

    ৭.২ টেমপ্লেট ফোল্ডার জানিয়ে দিন

    python

    TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], # 👈 শুধু এই লাইনটি বদলান "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ]
    • DIRS = প্রজেক্টের রুটে যে templates ফোল্ডার বানাব, সেখানে Django HTML খুঁজবে।
    • BASE_DIR = প্রজেক্টের মূল ফোল্ডার (djnagosite), ফাইলের উপরে আগেই ডিফাইন করা আছে।

    ৭.৩ ভাষা ও সময়

    python

    LANGUAGE_CODE = "en-us" TIME_ZONE = "Asia/Dhaka" # 👈 বাংলাদেশ সময় USE_I18N = True USE_TZ = True

    ৭.৪ Static ও Media (ফাইলের নিচের দিকে)

    STATIC_URL = "static/" লাইনটি খুঁজে সেটিকে এভাবে সম্পূর্ণ করুন:

    python

    # ---------- Static files (CSS, JS, নিজের বানানো ছবি) ---------- STATIC_URL = "static/" STATICFILES_DIRS = [BASE_DIR / "static"] # ডেভেলপমেন্টে এখান থেকে পড়বে STATIC_ROOT = BASE_DIR / "staticfiles" # VPS-এ collectstatic এখানে জমা করবে # ---------- Media files (ইউজার/অ্যাডমিন যে ছবি আপলোড করবে) ---------- MEDIA_URL = "media/" MEDIA_ROOT = BASE_DIR / "media" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
    সেটিংপার্থক্য
    STATICFILES_DIRSআপনি যে CSS/JS লেখেন
    STATIC_ROOTসব static এক জায়গায় জমা করার গুদাম (শুধু প্রোডাকশন)
    MEDIA_ROOTইউজার আপলোড করা ফাইল (প্রোডাক্ট/কোর্সের ছবি)

    ৮. Model তৈরি (ডেটাবেজ — এডুকেশন ও ই-কমার্স দুটোরই ভিত্তি)

    ছবি আপলোডের জন্য Pillow লাগবে:

    powershell

    pip install Pillow

    pages/models.py — পুরোটা রিপ্লেস করুন:

    python

    from django.db import models from django.urls import reverse class Course(models.Model): """একটি কোর্স = ই-কমার্সের একটি প্রোডাক্টের মতোই।""" title = models.CharField("কোর্সের নাম", max_length=200) slug = models.SlugField(max_length=220, unique=True, help_text="URL-এ ব্যবহার হবে, যেমন: python-basic") short_description = models.CharField(max_length=300, blank=True) description = models.TextField(blank=True) price = models.DecimalField(max_digits=10, decimal_places=2, default=0) thumbnail = models.ImageField(upload_to="courses/", blank=True, null=True) is_published = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = "Course" verbose_name_plural = "Courses" ordering = ["-created_at"] # নতুন কোর্স আগে দেখাবে def __str__(self): return self.title class ContactMessage(models.Model): """Contact পেইজের ফর্ম থেকে আসা মেসেজ এখানে জমা হবে।""" name = models.CharField(max_length=100) email = models.EmailField() subject = models.CharField(max_length=150, blank=True) message = models.TextField() created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ["-created_at"] def __str__(self): return f"{self.name} — {self.subject or 'No subject'}"

    Field-গুলোর ব্যাখ্যা

    Fieldব্যবহারমনে রাখার কথা
    CharFieldছোট টেক্সটmax_length বাধ্যতামূলক
    TextFieldবড় টেক্সটলিমিট নেই
    SlugFieldURL-বান্ধব টেক্সটunique=True দিলে ডুপ্লিকেট হবে না
    DecimalFieldটাকা/দামটাকার জন্য FloatField নয়, সবসময় DecimalField (হিসাবে ভুল হয় না)
    ImageFieldছবিPillow লাগে; upload_to = MEDIA_ROOT-এর ভেতরের সাব-ফোল্ডার
    BooleanFieldহ্যাঁ/নাড্রাফট-পাবলিশ কন্ট্রোলের জন্য দারুণ
    auto_now_add=Trueতৈরির সময় একবার বসেauto_now=True হলে প্রতিবার সেভে আপডেট হয়
    blank=Trueফর্মে খালি রাখা যাবেnull=True = ডেটাবেজে NULL রাখা যাবে

    ৮.১ মাইগ্রেশন (model → আসল টেবিল)

    powershell

    python manage.py makemigrations python manage.py migrate
    কমান্ডকাজ
    makemigrationsআপনার Python কোড দেখে পরিবর্তনের "নকশা" ফাইল বানায়
    migrateসেই নকশা ডেটাবেজে প্রয়োগ করে

    👉 নিয়ম: models.py-তে যেকোনো পরিবর্তন করলেই এই দুটো কমান্ড চালাতে হবে।


    ৯. Admin প্যানেল সেটআপ (Django-র সবচেয়ে বড় সুবিধা)

    pages/admin.py:

    python

    from django.contrib import admin from .models import ContactMessage, Course @admin.register(Course) class CourseAdmin(admin.ModelAdmin): list_display = ("title", "price", "is_published", "created_at") list_filter = ("is_published",) search_fields = ("title", "short_description") prepopulated_fields = {"slug": ("title",)} # নাম লিখলেই slug অটো তৈরি হবে list_editable = ("price", "is_published") # লিস্ট থেকেই এডিট করা যাবে @admin.register(ContactMessage) class ContactMessageAdmin(admin.ModelAdmin): list_display = ("name", "email", "subject", "created_at") search_fields = ("name", "email", "message") readonly_fields = ("name", "email", "subject", "message", "created_at")

    অ্যাডমিন ইউজার (superuser) বানান:

    powershell

    python manage.py createsuperuser

    Username, Email, Password দিন (পাসওয়ার্ড টাইপ করলে স্ক্রিনে কিছু দেখাবে না — এটা স্বাভাবিক, লিখে Enter চাপুন)।

    সার্ভার চালু করে যান 👉 http://127.0.0.1:8000/admin/ → লগইন করে ২-৩টি কোর্স যোগ করুন (দাম ও ছবি সহ)। এই ডেটাই পরে ওয়েবসাইটে দেখাবে।


    ১০. View তৈরি (লজিক)

    pages/views.py — পুরোটা রিপ্লেস:

    python

    from django.contrib import messages from django.shortcuts import redirect, render from .forms import ContactForm from .models import Course def home(request): """হোম পেইজ — সর্বশেষ ৩টি কোর্স দেখাবে।""" latest_courses = Course.objects.filter(is_published=True)[:3] context = { "page_title": "হোম", "courses": latest_courses, } return render(request, "pages/home.html", context) def course_list(request): """সব কোর্সের লিস্ট + সার্চ সুবিধা।""" query = request.GET.get("q", "").strip() courses = Course.objects.filter(is_published=True) if query: courses = courses.filter(title__icontains=query) context = { "page_title": "কোর্সসমূহ", "courses": courses, "query": query, } return render(request, "pages/courses.html", context) def contact(request): """যোগাযোগ ফর্ম — POST হলে ডেটাবেজে সেভ করে।""" if request.method == "POST": form = ContactForm(request.POST) if form.is_valid(): form.save() messages.success(request, "ধন্যবাদ! আপনার মেসেজ আমরা পেয়েছি।") return redirect("pages:contact") # PRG প্যাটার্ন: রিফ্রেশে ডাবল সাবমিট হবে না else: form = ContactForm() return render(request, "pages/contact.html", {"page_title": "যোগাযোগ", "form": form})

    লাইন-বাই-লাইন মূল ধারণা

    কোডঅর্থ
    def home(request)প্রতিটি view একটি ফাংশন, প্রথম আর্গুমেন্ট সবসময় request
    Course.objects.filter(...)SQL না লিখেই ডেটাবেজ কুয়েরি (ORM)
    [:3]মাত্র ৩টি রেকর্ড (SQL LIMIT 3)
    title__icontains=queryনামের মধ্যে খোঁজা, বড়-ছোট হাতের অক্ষর ধরবে না
    contextটেমপ্লেটে পাঠানো ডেটার ডিকশনারি
    render(request, template, context)HTML বানিয়ে রেসপন্স দেয়
    redirect("pages:contact")অন্য URL-এ পাঠায়

    ১১. Form তৈরি

    নতুন ফাইল বানান: pages/forms.py

    python

    from django import forms from .models import ContactMessage class ContactForm(forms.ModelForm): class Meta: model = ContactMessage fields = ["name", "email", "subject", "message"] widgets = { "name": forms.TextInput(attrs={"class": "input", "placeholder": "আপনার নাম"}), "email": forms.EmailInput(attrs={"class": "input", "placeholder": "you@example.com"}), "subject": forms.TextInput(attrs={"class": "input", "placeholder": "বিষয়"}), "message": forms.Textarea(attrs={"class": "input", "rows": 5, "placeholder": "আপনার মেসেজ লিখুন..."}), } def clean_message(self): """কাস্টম ভ্যালিডেশন: মেসেজ খুব ছোট হলে গ্রহণ করব না।""" message = self.cleaned_data["message"] if len(message) < 10: raise forms.ValidationError("মেসেজ কমপক্ষে ১০ অক্ষরের হতে হবে।") return message

    ModelForm কেন? model-এর ফিল্ড দেখে Django নিজেই ফর্ম, ভ্যালিডেশন আর .save() বানিয়ে দেয় — হাতে HTML ফর্ম ও ভ্যালিডেশন লিখতে হয় না। এটাই Django-র "DRY" (Don't Repeat Yourself) দর্শন।


    ১২. URL রাউটিং (২ ধাপে)

    ১২.১ অ্যাপের URL — নতুন ফাইল pages/urls.py

    python

    from django.urls import path from . import views app_name = "pages" # namespace: টেমপ্লেটে 'pages:home' লিখতে পারব urlpatterns = [ path("", views.home, name="home"), path("courses/", views.course_list, name="courses"), path("contact/", views.contact, name="contact"), ]

    ১২.২ মেইন URL — shikkhabazar/urls.py পুরোটা রিপ্লেস

    python

    from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.urls import include, path urlpatterns = [ path("admin/", admin.site.urls), path("", include("pages.urls")), # সব রুট pages অ্যাপে পাঠিয়ে দিলাম ] # ডেভেলপমেন্টে আপলোড করা ছবি দেখানোর জন্য (প্রোডাকশনে Nginx এই কাজ করবে) if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    ধারণাব্যাখ্যা
    path("courses/", view, name=...)/courses/ লিংকে ওই view চলবে
    name="courses"টেমপ্লেটে {% url 'pages:courses' %} লিখে লিংক বানাব
    include()অ্যাপের urls.py-কে জুড়ে দেয় — প্রজেক্ট বড় হলেও গোছানো থাকে
    হার্ডকোড লিংক? ❌href="/courses/" না লিখে {% url %} ব্যবহার করুন; URL বদলালেও সাইট ভাঙবে না

    ১৩. Template তৈরি (চেহারা)

    VS Code-এ প্রজেক্টের রুটে (যেখানে manage.py আছে) এই ফোল্ডারগুলো বানান:

    templates/ ├── base.html └── pages/ ├── home.html ├── courses.html └── contact.html

    ১৩.১ templates/base.html — সব পেইজের কমন কাঠামো

    html

    {% load static %} <!DOCTYPE html> <html lang="bn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}ShikkhaBazar{% endblock %}</title> <link rel="stylesheet" href="{% static 'css/style.css' %}"> </head> <body> <header class="navbar"> <a class="logo" href="{% url 'pages:home' %}">Shikkha<span>Bazar</span></a> <nav> <a href="{% url 'pages:home' %}">হোম</a> <a href="{% url 'pages:courses' %}">কোর্স</a> <a href="{% url 'pages:contact' %}">যোগাযোগ</a> </nav> </header> <main class="container"> {% if messages %} {% for message in messages %} <div class="alert alert-{{ message.tags }}">{{ message }}</div> {% endfor %} {% endif %} {% block content %}{% endblock %} </main> <footer class="footer"> <p>&copy; {% now "Y" %} ShikkhaBazar — Django দিয়ে তৈরি।</p> </footer> </body> </html>

    টেমপ্লেট সিনট্যাক্সের ৩টি নিয়ম:

    লেখাকাজউদাহরণ
    {{ ... }}ভ্যালু দেখায়{{ course.title }}
    {% ... %}লজিক/ট্যাগ{% if %}, {% for %}, {% url %}
    {# ... #}কমেন্ট{# এটা দেখাবে না #}

    {% block content %} = "ফাঁকা জায়গা"; প্রতিটি পেইজ এখানে নিজের কনটেন্ট বসাবে। এটাই template inheritance — নেভবার/ফুটার একবার লিখলেই সব পেইজে চলে আসবে।

    ১৩.২ templates/pages/home.html

    html

    {% extends "base.html" %} {% load static %} {% block title %}হোম | ShikkhaBazar{% endblock %} {% block content %} <section class="hero"> <h1>ঘরে বসে দক্ষতা অর্জন করুন</h1> <p>প্রোগ্রামিং, ডিজাইন ও ব্যবসা — সবকিছুর কোর্স একই জায়গায়।</p> <a class="btn" href="{% url 'pages:courses' %}">সব কোর্স দেখুন</a> </section> <h2 class="section-title">সর্বশেষ কোর্স</h2> <div class="grid"> {% for course in courses %} <article class="card"> {% if course.thumbnail %} <img src="{{ course.thumbnail.url }}" alt="{{ course.title }}"> {% endif %} <h3>{{ course.title }}</h3> <p>{{ course.short_description }}</p> <div class="card-foot"> <span class="price">৳ {{ course.price }}</span> </div> </article> {% empty %} <p class="muted">এখনো কোনো কোর্স যোগ করা হয়নি। অ্যাডমিন প্যানেল থেকে যোগ করুন।</p> {% endfor %} </div> {% endblock %}

    👉 {% empty %} = লিস্ট খালি থাকলে যা দেখাবে। খুব কাজের ট্যাগ।

    ১৩.৩ templates/pages/courses.html

    html

    {% extends "base.html" %} {% block title %}কোর্সসমূহ | ShikkhaBazar{% endblock %} {% block content %} <h1 class="section-title">সকল কোর্স</h1> <form class="search" method="get" action="{% url 'pages:courses' %}"> <input class="input" type="text" name="q" value="{{ query }}" placeholder="কোর্স খুঁজুন..."> <button class="btn" type="submit">খুঁজুন</button> </form> {% if query %} <p class="muted">"{{ query }}" — এর জন্য {{ courses|length }} টি ফলাফল।</p> {% endif %} <div class="grid"> {% for course in courses %} <article class="card"> {% if course.thumbnail %} <img src="{{ course.thumbnail.url }}" alt="{{ course.title }}"> {% endif %} <h3>{{ course.title }}</h3> <p>{{ course.short_description }}</p> <p class="muted">{{ course.description|truncatewords:18 }}</p> <div class="card-foot"> <span class="price">৳ {{ course.price }}</span> <span class="muted">{{ course.created_at|date:"d M Y" }}</span> </div> </article> {% empty %} <p class="muted">কোনো কোর্স পাওয়া যায়নি।</p> {% endfor %} </div> {% endblock %}

    Template filter (| চিহ্ন) দিয়ে ডেটা সাজানো যায়:

    ফিল্টারকাজ
    |truncatewords:18১৮ শব্দের পর ...
    |date:"d M Y"তারিখ ফরম্যাট
    |lengthসংখ্যা গোনা
    |default:"নেই"খালি হলে বিকল্প লেখা

    ১৩.৪ templates/pages/contact.html

    html

    {% extends "base.html" %} {% block title %}যোগাযোগ | ShikkhaBazar{% endblock %} {% block content %} <h1 class="section-title">যোগাযোগ করুন</h1> <div class="two-col"> <form class="card form" method="post" novalidate> {% csrf_token %} {% if form.non_field_errors %} <div class="alert alert-error">{{ form.non_field_errors }}</div> {% endif %} {% for field in form %} <div class="field"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} {% if field.errors %} <small class="error">{{ field.errors|join:", " }}</small> {% endif %} </div> {% endfor %} <button class="btn" type="submit">মেসেজ পাঠান</button> </form> <aside class="card"> <h3>আমাদের ঠিকানা</h3> <p>ঢাকা, বাংলাদেশ</p> <p>ইমেইল: support@shikkhabazar.test</p> <p>ফোন: +880 1XXX-XXXXXX</p> </aside> </div> {% endblock %}

    🔐 {% csrf_token %} ছাড়া POST ফর্ম কাজ করবে না (403 Forbidden দেবে)। এটি Django-র সিকিউরিটি — অন্য সাইট থেকে জাল রিকোয়েস্ট আটকায়। প্রতিটি method="post" ফর্মে এটি বাধ্যতামূলক।


    ১৪. CSS যোগ করা (static file)

    ফোল্ডার বানান: static/css/style.css (প্রজেক্টের রুটে)।

    static/css/style.css

    css

    :root { --brand: #0f766e; --dark: #0f172a; --muted: #64748b; --bg: #f8fafc; --line: #e2e8f0; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: "Segoe UI", "Nirmala UI", system-ui, sans-serif; background: var(--bg); color: var(--dark); line-height: 1.7; } /* ---------- Navbar ---------- */ .navbar { display: flex; justify-content: space-between; align-items: center; padding: 16px 32px; background: #fff; border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 10; } .logo { font-size: 22px; font-weight: 700; color: var(--dark); text-decoration: none; } .logo span { color: var(--brand); } .navbar nav a { margin-left: 18px; color: var(--muted); text-decoration: none; font-weight: 600; } .navbar nav a:hover { color: var(--brand); } /* ---------- Layout ---------- */ .container { max-width: 1060px; margin: 0 auto; padding: 32px 20px 60px; } .section-title { font-size: 26px; margin: 26px 0 18px; } .muted { color: var(--muted); font-size: 14px; } .hero { background: linear-gradient(135deg, var(--brand), #115e59); color: #fff; padding: 56px 32px; border-radius: 16px; text-align: center; } .hero h1 { font-size: 34px; margin-bottom: 10px; } .btn { display: inline-block; margin-top: 14px; padding: 11px 22px; background: #fff; color: var(--brand); border: 0; border-radius: 8px; font-weight: 700; cursor: pointer; text-decoration: none; } .hero .btn:hover { opacity: .9; } form .btn { background: var(--brand); color: #fff; } /* ---------- Cards ---------- */ .grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); } .card { background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 18px; } .card img { width: 100%; height: 160px; object-fit: cover; border-radius: 10px; margin-bottom: 12px; } .card h3 { font-size: 18px; margin-bottom: 6px; } .card-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; } .price { color: var(--brand); font-weight: 700; } /* ---------- Forms ---------- */ .two-col { display: grid; gap: 20px; grid-template-columns: 2fr 1fr; } .field { margin-bottom: 14px; } .field label { display: block; font-weight: 600; margin-bottom: 5px; font-size: 14px; } .input { width: 100%; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; font-size: 15px; font-family: inherit; } .input:focus { outline: 2px solid var(--brand); border-color: transparent; } .search { display: flex; gap: 10px; margin-bottom: 20px; } .error { color: #dc2626; font-size: 13px; } /* ---------- Alerts ---------- */ .alert { padding: 12px 16px; border-radius: 10px; margin-bottom: 18px; font-weight: 600; } .alert-success { background: #dcfce7; color: #166534; } .alert-error { background: #fee2e2; color: #991b1b; } /* ---------- Footer ---------- */ .footer { text-align: center; padding: 22px; color: var(--muted); border-top: 1px solid var(--line); background: #fff; } @media (max-width: 720px) { .two-col { grid-template-columns: 1fr; } .navbar { flex-direction: column; gap: 10px; } }

    গুরুত্বপূর্ণ: HTML-এ CSS লিংক করতে হলে টেমপ্লেটের একদম উপরে {% load static %} থাকতে হবে, তারপর {% static 'css/style.css' %}। সরাসরি href="/static/css/style.css" লিখবেন না — VPS-এ CDN/পাথ বদলালে ভেঙে যাবে।


    ১৫. সাইট চালান 🚀

    powershell

    python manage.py runserver
    পেইজলিংক
    হোমhttp://127.0.0.1:8000/
    কোর্সhttp://127.0.0.1:8000/courses/
    যোগাযোগhttp://127.0.0.1:8000/contact/
    অ্যাডমিনhttp://127.0.0.1:8000/admin/

    টেস্ট করুন: অ্যাডমিন থেকে কোর্স যোগ করুন → হোম/কোর্স পেইজে দেখাবে। Contact ফর্ম সাবমিট করুন → সবুজ সাকসেস মেসেজ আসবে এবং অ্যাডমিনের Contact messages-এ জমা হবে। ✅

    চূড়ান্ত ফোল্ডার স্ট্রাকচার

    djnagosite/ ├── venv/ ├── db.sqlite3 ├── manage.py ├── requirements.txt ├── media/ ← আপলোড করা ছবি (অটো তৈরি হবে) ├── shikkhabazar/ │ ├── __init__.py settings.py urls.py asgi.py wsgi.py ├── pages/ │ ├── migrations/ __init__.py admin.py apps.py │ ├── forms.py models.py tests.py urls.py views.py ├── static/css/style.css └── templates/ ├── base.html └── pages/home.html courses.html contact.html

    শেষে প্যাকেজ লিস্ট সেভ করে রাখুন (VPS-এ হুবহু একই এনভায়রনমেন্ট বানাতে লাগবে):

    powershell

    pip freeze > requirements.txt

    ১৬. সাধারণ এরর ও সমাধান

    এররকারণসমাধান
    Activate.ps1 cannot be loadedExecution policySet-ExecutionPolicy RemoteSigned -Scope CurrentUser
    django-admin : not recognizedvenv activate করা হয়নি.\venv\Scripts\Activate.ps1
    TemplateDoesNotExistপাথ ভুল / DIRS সেট করা হয়নিtemplates/pages/home.html পাথ ও settings.py-এর DIRS চেক করুন
    NoReverseMatch{% url %}-এর নাম ভুলapp_name + name মিলিয়ে দেখুন: 'pages:home'
    no such table: pages_coursemigrate করা হয়নিmakemigrations → migrate
    CSRF verification failedফর্মে {% csrf_token %} নেইফর্মের ভেতরে যোগ করুন
    CSS কাজ করছে না{% load static %} নেই, বা ফোল্ডার ভুলপাথ ঠিক করে Ctrl+F5 দিয়ে হার্ড রিফ্রেশ
    ModuleNotFoundError: No module named 'pages'INSTALLED_APPS-এ নেইঅ্যাপ নাম যোগ করুন
    Port already in useআগের সার্ভার চলছেCtrl+C, বা python manage.py runserver 8001
    ছবি দেখা যাচ্ছে নাMEDIA কনফিগ/urls.pyMEDIA_URL, MEDIA_ROOT এবং urls.py-এর static(...) লাইন চেক করুন

    ১৭. VPS-এ (প্রোডাকশন) যাওয়ার প্রস্তুতি — এখনই যা ঠিক করতে হবে

    ডেভেলপমেন্ট আর প্রোডাকশন এক নয়। runserver কখনোই প্রোডাকশনে ব্যবহার করবেন না।

    ১৭.১ গোপন তথ্য .env ফাইলে সরান

    powershell

    pip install python-dotenv

    settings.py-এর উপরের দিকে:

    python

    import os from pathlib import Path from dotenv import load_dotenv BASE_DIR = Path(__file__).resolve().parent.parent load_dotenv(BASE_DIR / ".env") SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "dev-only-unsafe-key") DEBUG = os.environ.get("DJANGO_DEBUG", "True") == "True" ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "127.0.0.1,localhost").split(",") CSRF_TRUSTED_ORIGINS = [ o for o in os.environ.get("DJANGO_CSRF_TRUSTED", "").split(",") if o ]

    প্রজেক্ট রুটে .env ফাইল (লোকাল):

    DJANGO_SECRET_KEY=local-dev-key-change-me DJANGO_DEBUG=True DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost

    VPS-এর .env:

    DJANGO_SECRET_KEY=<নতুন-লম্বা-র‍্যান্ডম-কি> DJANGO_DEBUG=False DJANGO_ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com DJANGO_CSRF_TRUSTED=https://yourdomain.com,https://www.yourdomain.com

    নতুন SECRET_KEY বানানোর কমান্ড:

    powershell

    python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"

    .gitignore ফাইল (রুটে) বানিয়ে লিখুন:

    venv/ __pycache__/ *.pyc db.sqlite3 .env media/ staticfiles/

    ১৭.২ প্রোডাকশনে যা যোগ করবেন (DEBUG = False হলে)

    python

    if not DEBUG: SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True X_FRAME_OPTIONS = "DENY"

    ডিপ্লয়ের আগে সবসময় চালাবেন:

    powershell

    python manage.py check --deploy

    ১৭.৩ VPS-এর রোডম্যাপ (Ubuntu 24.04 LTS)

    ধাপকমান্ড/কাজ
    ১sudo apt update && sudo apt install python3-venv python3-pip nginx postgresql -y
    ২PostgreSQL-এ ডেটাবেজ ও ইউজার তৈরি; pip install psycopg[binary]; settings.py-এ DATABASES বদল
    ৩কোড আপলোড (git clone) → python3 -m venv venv → pip install -r requirements.txt
    ৪python manage.py migrate → python manage.py collectstatic → createsuperuser
    ৫pip install gunicorn; systemd service বানিয়ে gunicorn shikkhabazar.wsgi:application চালান (socket দিয়ে)
    ৬Nginx-এ reverse proxy + /static/ ও /media/ সার্ভ করার কনফিগ
    ৭sudo apt install certbot python3-certbot-nginx → sudo certbot --nginx (ফ্রি HTTPS)
    ৮sudo ufw allow OpenSSH; sudo ufw allow 'Nginx Full'; sudo ufw enable

    Nginx-এর মূল অংশটা দেখতে এমন হবে:

    nginx

    server { server_name yourdomain.com www.yourdomain.com; location /static/ { alias /home/ubuntu/djnagosite/staticfiles/; } location /media/ { alias /home/ubuntu/djnagosite/media/; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } }

    মনে রাখবেন: Nginx = দরজার দরবান (static ফাইল ও HTTPS), Gunicorn = Python কোড চালানোর ইঞ্জিন, Django = আপনার অ্যাপ।


    ১৮. এরপর কী শিখবেন (আপনার লক্ষ্য অনুযায়ী ক্রম)

    ধাপবিষয়এডুকেশন সাইটেই-কমার্সে
    ১Detail view + slug URL (path("courses/<slug:slug>/"), get_object_or_404)কোর্স ডিটেইলপ্রোডাক্ট ডিটেইল
    ২Model relations (ForeignKey, ManyToManyField)Category, Lesson, InstructorCategory, Variant
    ৩Pagination (Paginator)কোর্স লিস্টপ্রোডাক্ট লিস্ট
    ৪User auth (django.contrib.auth, login/signup)স্টুডেন্ট অ্যাকাউন্টকাস্টমার অ্যাকাউন্ট
    ৫Sessionকোর্স প্রগ্রেসকার্ট
    ৬Forms + Email (send_mail, SMTP)ভর্তি ফর্মঅর্ডার কনফার্মেশন
    ৭Class-Based Views (ListView, DetailView)কম কোডে বেশি কাজঐ
    ৮Payment gateway (SSLCOMMERZ/bKash/Stripe API)কোর্স কেনাচেকআউট
    ৯Django REST Frameworkমোবাইল অ্যাপ/APIঐ

    শেখার সবচেয়ে ভালো রেফারেন্স: অফিসিয়াল ডকুমেন্টেশন — https://docs.djangoproject.com/en/5.2/ এবং টিউটোরিয়াল (Polls app): https://docs.djangoproject.com/en/5.2/intro/tutorial01/


    ১৯. রোজকার কমান্ড চিটশিট

    powershell

    cd $HOME\Desktop\djnagosite # প্রজেক্টে ঢোকা .\venv\Scripts\Activate.ps1 # venv চালু (প্রতিদিন প্রথম কাজ) python manage.py runserver # সার্ভার চালু (বন্ধ: Ctrl+C) python manage.py makemigrations # model বদলালে python manage.py migrate # ডেটাবেজে প্রয়োগ python manage.py createsuperuser # অ্যাডমিন ইউজার python manage.py shell # ডেটাবেজ নিয়ে পরীক্ষা python manage.py collectstatic # প্রোডাকশনের আগে python manage.py check --deploy # ডিপ্লয়ের আগে সিকিউরিটি চেক pip freeze > requirements.txt # প্যাকেজ লিস্ট সেভ deactivate # venv বন্ধ

    ধাপগুলো ঠিক ক্রমে করলে কোনো এরর আসবে না। কোনো ধাপে আটকে গেলে PowerShell-এর পুরো লাল এরর মেসেজটা আমাকে কপি করে পাঠিয়ে দিন — ঠিক করে দেব।

    পরের ধাপে কী করতে চান — (ক) কোর্স ডিটেইল পেইজ + Category যোগ করা, (খ) লগইন/রেজিস্ট্রেশন সিস্টেম, নাকি (গ) ই-কমার্স কার্ট? বলুন, সেটাই একইভাবে শূন্য থেকে ব্যাখ্যা করে দেব।

  • Post a Comment

    0 Comments

    Post a Comment (0)