আমি windows 10 use করি।এখন আমি আমার desktop এ djnagosite নামে একটা ফোল্ডার এ তোমার ইচ্ছামত নাম দিয়ে একটা ৩ পেইজের ওয়েবসাইট বানিয়ে দাও। আমি windows powershell and vs code editor ইউজ করতে চাই। একেবারে শূন্য থেকে খুব ভালো করে সহজ করে শিখিয়ে দাও কোডের ব্যাখ্যা সহ ।আমার লক্ষ্য django দিয়ে যেকোনো এডুকেশন ওয়েবসাইট এবং ই কমার্স যেন বানাতে পারি,এখন শুরু করো। কোন ভুল করবে না। একেবারে সঠিক তথ্য ও কোড দিবে যেন ভবিষ্যতে vps এ সাইট বানাতে পারি djnago দিয়ে
•
12:40 AM
GPT 6 Astra
GPT 6 Astra
আমরা Django দিয়ে “EduShop” নামে একটি ৩ পেজের ওয়েবসাইট বানাব। এটি হবে তোমার ভবিষ্যতের এডুকেশন ওয়েবসাইট ও ই-কমার্স শেখার ভিত্তি।
আমি তোমার কম্পিউটারে সরাসরি ফাইল তৈরি করতে পারছি না; তবে কোন কমান্ড কোথায় চালাবে, কোন ফাইলে কী লিখবে এবং কোড কীভাবে কাজ করে—সব ধাপে ধাপে দেখাচ্ছি।
একটি বাস্তব কথা: কোড সঠিক হলেও Python-এর ইনস্টলেশন, ফোল্ডারের অবস্থান বা PowerShell-এর সেটিংসের কারণে সমস্যা হতে পারে। কোনো ধাপে error হলে পরের ধাপে না গিয়ে সেই error-এর সম্পূর্ণ লেখা পাঠাবে।
১. কী বানাব?
আমাদের সাইটে সাধারণ দর্শকদের জন্য তিনটি পেজ থাকবে:
পেজ ঠিকানা কাজ
হোম / ওয়েবসাইটের পরিচিতি
কোর্স /courses/ ডেটাবেস থেকে কোর্স দেখানো
যোগাযোগ /contact/ ফর্মের তথ্য ডেটাবেসে সংরক্ষণ
এগুলোর বাইরে Django-এর তৈরি Admin Panel থাকবে:
text
Copy
/admin/
সেখান থেকে তুমি:
নতুন কোর্স যোগ করতে পারবে।
কোর্সের দাম পরিবর্তন করতে পারবে।
কোর্স প্রকাশ বা লুকিয়ে রাখতে পারবে।
যোগাযোগ ফর্মে আসা মেসেজ দেখতে পারবে।
আমরা ব্যবহার করব:
Python 3.13
Django 5.2 LTS
HTML ও CSS
SQLite ডেটাবেস
Windows PowerShell
VS Code
Django 5.2 LTS বেছে নিচ্ছি কারণ এটি দীর্ঘমেয়াদি সাপোর্টের সংস্করণ। প্রথম প্রজেক্টে SQLite সহজ; পরে VPS-এ PostgreSQL ব্যবহার শিখব।
২. Django কীভাবে কাজ করে?
সহজ করে পুরো পথটি দেখো:
text
Copy
ব্রাউজারে ঠিকানা লেখা
↓
urls.py ঠিক করে কোন view চলবে
↓
views.py প্রয়োজনীয় কাজ করে
↓
প্রয়োজনে Model দিয়ে ডেটাবেস থেকে তথ্য আনে
↓
Template দিয়ে HTML তৈরি করে
↓
ব্রাউজারে পেজ দেখায়
মূল ধারণা:
বিষয় অর্থ
Project পুরো ওয়েবসাইটের সেটিংস ও মূল কাঠামো
App ওয়েবসাইটের একটি কাজের অংশ
Model ডেটাবেসে কী ধরনের তথ্য থাকবে তার Python সংজ্ঞা
View একটি request পেলে কী কাজ হবে
Template ব্রাউজারে দেখানোর HTML
URL কোন ঠিকানা কোন view চালাবে
Form ব্যবহারকারীর তথ্য গ্রহণ ও যাচাই করার ব্যবস্থা
আমাদের project-এর নাম হবে config, আর app-এর নাম হবে core।
config শুধু ভেতরের Python package-এর নাম। ওয়েবসাইটের নাম EduShop।
৩. Python ও VS Code প্রস্তুত করো
৩.১ Python ইনস্টল
অফিশিয়াল ওয়েবসাইট থেকে Python 3.13-এর Windows installer ইনস্টল করো:
https://www.python.org/downloads/windows/
ইনস্টল করার সময় সুযোগ থাকলে:
text
Copy
Add python.exe to PATH
অপশনটি নির্বাচন করো। Python Launcher-ও ইনস্টল রাখো।
ইনস্টল শেষে নতুন PowerShell খুলে চালাও:
powershell
Copy
py -3.13 --version
এ ধরনের ফলাফল আসবে:
text
Copy
Python 3.13.x
এখানে x-এর জায়গায় তোমার ইনস্টল করা patch version থাকবে।
ইনস্টল করা Python-এর তালিকা দেখতে:
powershell
Copy
py -0p
py command পাওয়া না গেলে Python installation/Launcher ঠিক করতে হবে। এই পরীক্ষা সফল হওয়ার পরেই এগোও।
৩.২ VS Code ইনস্টল
অফিশিয়াল লিংক:
https://code.visualstudio.com/
VS Code-এর Extensions থেকে ইনস্টল করো:
text
Copy
Python
Publisher: Microsoft
৪. Desktop-এ djnagosite ফোল্ডার তৈরি
তুমি ফোল্ডারের নাম djnagosite বলেছ, তাই সেই বানানই রাখছি।
PowerShell-এ নিচের কমান্ডগুলো চালাও:
powershell
Copy
$desktop = [Environment]::GetFolderPath("Desktop")
$projectPath = Join-Path $desktop "djnagosite"
New-Item -ItemType Directory -Path $projectPath -Force | Out-Null
Set-Location $projectPath
এভাবে Desktop যদি OneDrive-এর ভেতরেও থাকে, Windows-এর নির্ধারিত Desktop path ব্যবহার হবে।
তুমি কোথায় আছ দেখতে:
powershell
Copy
Get-Location
ফলাফলের শেষে থাকা উচিত:
text
Copy
Desktop\djnagosite
ফোল্ডারটিতে আগে থেকে কোনো Django project থাকলে সেটির ওপর এই tutorial-এর ফাইল লিখবে না। আগে backup রাখবে।
৫. Virtual environment তৈরি
একেক প্রজেক্টের Python package আলাদা রাখার জন্য virtual environment ব্যবহার করা হয়।
চালাও:
powershell
Copy
py -3.13 -m venv .venv
তারপর activate করো:
powershell
Copy
.\.venv\Scripts\Activate.ps1
সফল হলে PowerShell prompt-এর শুরুতে সাধারণত দেখাবে:
text
Copy
(.venv)
যদি script execution error আসে
শুধু বর্তমান PowerShell session-এর জন্য চালাও:
powershell
Copy
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
তারপর আবার:
powershell
Copy
.\.venv\Scripts\Activate.ps1
এটি চালাতে সাধারণত Administrator হিসেবে PowerShell খোলার প্রয়োজন নেই। কোনো অফিসের managed computer হলে প্রতিষ্ঠানের policy এটি আটকাতে পারে।
সঠিক Python ব্যবহার হচ্ছে কি না দেখো:
powershell
Copy
python -c "import sys; print(sys.executable)"
ফলাফলের শেষে থাকবে:
text
Copy
djnagosite\.venv\Scripts\python.exe
Virtual environment activate করতে না পারলেও নির্দিষ্ট Python সরাসরি চালানো যায়: .\.venv\Scripts\python.exe। তবে পরের নির্দেশনাগুলোতে ধরে নিচ্ছি environment activate করা আছে।
৬. Django ইনস্টল
চাল
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:41 AM
m
You
Continue
•
12:42 AM
GPT 6 Astra
GPT 6 Astra
আগের ধাপে আমরা Desktop-এর djnagosite ফোল্ডারে virtual environment তৈরি ও activate করেছি। এবার Django ইনস্টল করে পুরো ওয়েবসাইট বানাব।
এখন থেকে সব PowerShell কমান্ড djnagosite ফোল্ডারে চালাবে।
Terminal-এর শুরুতে (.venv) থাকা উচিত। কোডের মধ্যে দেওয়া >>> বা prompt কপি করার প্রয়োজন নেই—আমি কমান্ডগুলো আলাদা করে দিচ্ছি।
৬. Django ইনস্টল করো
PowerShell-এ চালাও:
powershell
Copy
python -m pip install --upgrade pip
python -m pip install "Django>=5.2,<5.3"
এতে Django 5.2 সিরিজের সর্বশেষ উপলব্ধ patch release ইনস্টল হবে; 5.3 বা 6.0 ইনস্টল হবে না।
ইনস্টল ঠিক হয়েছে কি না দেখো:
powershell
Copy
python -m django --version
ফলাফল হবে:
text
Copy
5.2.x
এখানে x তোমার ইনস্টল হওয়া patch version।
কমান্ডের ব্যাখ্যা
python -m pip: বর্তমানে নির্বাচিত Python-এর package installer চালায়।
install: package ইনস্টল করে।
Django>=5.2,<5.3: কোন version range চাই তা নির্ধারণ করে।
৭. Project ও app তৈরি করো
প্রথমে Django project:
powershell
Copy
python -m django startproject config .
শেষের . খুব গুরুত্বপূর্ণ। এর অর্থ: বর্তমান djnagosite ফোল্ডারের মধ্যেই project তৈরি করো।
এখন app তৈরি করো:
powershell
Copy
python manage.py startapp core
বর্তমানে কাঠামো হবে:
text
Copy
djnagosite/
├── .venv/
├── config/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── core/
│ ├── migrations/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
গুরুত্বপূর্ণ ফাইল
ফাইল কাজ
manage.py Django-এর বিভিন্ন command চালায়
config/settings.py পুরো project-এর configuration
config/urls.py মূল URL তালিকা
core/models.py ডেটাবেসের কাঠামো
core/views.py পেজের logic
core/admin.py Admin Panel-এর configuration
.venv-এর ভেতরে তোমার ওয়েবসাইটের কোনো কোড লিখবে না।
৮. VS Code-এ project খোলো
PowerShell-এ:
powershell
Copy
code .
যদি code command পাওয়া না যায়:
VS Code খোলো।
File → Open Folder নির্বাচন করো।
Desktop-এর djnagosite ফোল্ডার খোলো।
Python interpreter নির্বাচন
VS Code-এ:
Ctrl + Shift + P চাপো।
লিখো: Python: Select Interpreter
.venv-এর interpreter নির্বাচন করো।
যদি তালিকায় না থাকে, Enter interpreter path থেকে নির্বাচন করো:
text
Copy
djnagosite\.venv\Scripts\python.exe
VS Code-এর PowerShell terminal
Terminal → New Terminal দিয়ে terminal খোলো।
Terminal PowerShell না হলে terminal-এর পাশের dropdown থেকে PowerShell নির্বাচন করো।
নতুন terminal-এ প্রয়োজন হলে activate করো:
powershell
Copy
.\.venv\Scripts\Activate.ps1
এবং যাচাই করো:
powershell
Copy
Get-Location
বর্তমান ফোল্ডার হতে হবে djnagosite।
৯. Templates ও CSS-এর ফোল্ডার তৈরি
PowerShell-এ চালাও:
powershell
Copy
New-Item -ItemType Directory -Force -Path "templates\core", "static\css" | Out-Null
এবার VS Code Explorer থেকে নিচের নতুন ফাইলগুলো তৈরি করো:
text
Copy
core/urls.py
core/forms.py
templates/base.html
templates/core/home.html
templates/core/courses.html
templates/core/contact.html
static/css/style.css
VS Code-এ কোনো folder-এর ওপর right-click করে New File নির্বাচন করলে ফাইল তৈরি করা যায়।
১০. Django settings ঠিক করো
খোলো:
text
Copy
config/settings.py
এই ফাইলে কিছু অংশ পরিবর্তন করব। পুরো ফাইল মুছে ফেলবে না।
১০.১ App register করো
INSTALLED_APPS খুঁজে এটিকে এমন করো:
python
Copy
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"core.apps.CoreConfig",
]
শেষের লাইনটি Django-কে আমাদের core app সম্পর্কে জানায়।
১০.২ Templates folder নির্ধারণ করো
TEMPLATES অংশ খুঁজে শুধু DIRS লাইনটি বদলাও:
python
Copy
"DIRS": [BASE_DIR / "templates"],
পরিবর্তনের পর পুরো অংশটি হবে:
python
Copy
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",
],
},
},
]
ব্যাখ্যা:
BASE_DIR: project-এর মূল ফোল্ডার।
BASE_DIR / "templates": সেই ফোল্ডারের templates directory।
APP_DIRS=True: app-এর ভেতরের template directory-ও খোঁজে।
১০.৩ ভাষা ও সময়
বিদ্যমান
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:43 AM
m
You
Continue
•
12:43 AM
GPT 6 Astra
GPT 6 Astra
আমরা config/settings.py ফাইলের সেটিংস ঠিক করছিলাম। সেখান থেকেই শুরু করি।
আজকের বাকি ধাপগুলো শেষ করলে তোমার সাইটে থাকবে:
সুন্দর হোম পেজ।
ডেটাবেস থেকে দেখানো কোর্সের তালিকা।
কার্যকর যোগাযোগ ফর্ম।
কোর্স ও মেসেজ পরিচালনার Admin Panel।
মনে রাখবে: সব command চালাবে djnagosite ফোল্ডারে, যেখানে manage.py আছে। আর প্রতিটি ফাইলের কোড লেখার পরে Ctrl + S দিয়ে save করবে।
১০.৩ ভাষা ও সময় নির্ধারণ
config/settings.py ফাইলে বিদ্যমান LANGUAGE_CODE, TIME_ZONE, USE_I18N এবং USE_TZ লাইনগুলো খুঁজে এমন করো:
python
Copy
LANGUAGE_CODE = "bn"
TIME_ZONE = "Asia/Dhaka"
USE_I18N = True
USE_TZ = True
ব্যাখ্যা
bn: Django-এর যেসব built-in লেখা বাংলায় অনূদিত আছে, সেগুলো বাংলায় দেখাবে।
Asia/Dhaka: বাংলাদেশের সময় অঞ্চল।
USE_I18N: অনুবাদ ব্যবস্থা চালু রাখে।
USE_TZ: timezone-aware তারিখ ও সময় ব্যবহার করে।
তুমি বাংলাদেশের বাইরে হলে প্রয়োজন অনুযায়ী timezone বদলাতে পারবে।
১০.৪ CSS-এর settings
একই ফাইলে STATIC_URL লাইনটি খুঁজে নিচের মতো করো। এরপর তার নিচে STATICFILES_DIRS যোগ করো:
python
Copy
STATIC_URL = "static/"
STATICFILES_DIRS = [
BASE_DIR / "static",
]
এতে Django আমাদের তৈরি static ফোল্ডার থেকে CSS খুঁজে পাবে।
১০.৫ স্থানীয়ভাবে ব্যবহারের host
ALLOWED_HOSTS খুঁজে পরিবর্তন করো:
python
Copy
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
এখন শেখার সময় এটি থাকবে:
python
Copy
DEBUG = True
VPS-এ live করার সময় DEBUG = False করতে হবে। আরও deployment settings লাগবে—শেষে সেটি বলছি।
১০.৬ Database এখন পরিবর্তন করতে হবে না
Django তৈরি করে দেওয়া এই configuration রাখো:
python
Copy
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
SQLite একটি ফাইলে তথ্য সংরক্ষণ করে। প্রথম project শেখার জন্য আলাদা database server ইনস্টল করতে হচ্ছে না।
১১. Model: ডেটাবেসের কাঠামো তৈরি
আমাদের দুটি ধরনের তথ্য রাখতে হবে:
কোর্স।
যোগাযোগের মেসেজ।
খোলো:
text
Copy
core/models.py
ফাইলের বর্তমান কোড বদলে নিচের কোড দাও:
python
Copy
from decimal import Decimal
from django.core.validators import MinValueValidator
from django.db import models
class Course(models.Model):
title = models.CharField("কোর্সের নাম", max_length=200)
description = models.TextField("বিবরণ")
price = models.DecimalField(
"মূল্য",
max_digits=10,
decimal_places=2,
validators=[MinValueValidator(Decimal("0.00"))],
)
is_published = models.BooleanField("প্রকাশিত", default=True)
created_at = models.DateTimeField("তৈরির সময়", auto_now_add=True)
class Meta:
ordering = ["-created_at", "-pk"]
verbose_name = "কোর্স"
verbose_name_plural = "কোর্সসমূহ"
def __str__(self):
return self.title
class ContactMessage(models.Model):
name = models.CharField("নাম", max_length=100)
email = models.EmailField("ইমেইল")
message = models.TextField("মেসেজ", max_length=2000)
created_at = models.DateTimeField("পাঠানোর সময়", auto_now_add=True)
class Meta:
ordering = ["-created_at", "-pk"]
verbose_name = "যোগাযোগের মেসেজ"
verbose_name_plural = "যোগাযোগের মেসেজসমূহ"
def __str__(self):
return f"{self.name} - {self.email}"
কোডের ব্যাখ্যা
class Course(models.Model)
Django-কে বলছি: Course একটি database model।
Migration চালানোর পরে এর জন্য database table তৈরি হবে।
Field-এর ধরন
Field কাজ
CharField ছোট লেখা
TextField বড় লেখা
EmailField ইমেইল সংরক্ষণ; form validation-এ ইমেইলের গঠন যাচাই
DecimalField নির্দিষ্ট দশমিক ঘরসহ সংখ্যা
BooleanField সত্য/মিথ্যা
DateTimeField তারিখ ও সময়
টাকার জন্য DecimalField কেন?
টাকার হিসাবের জন্য সাধারণত FloatField নয়, DecimalField ব্যবহার করা উচিত। এতে binary floating-point rounding-এর সমস্যা এড়ানো যায়।
python
Copy
max_digits=10
decimal_places=2
মানে সর্বোচ্চ ১০টি digit, যার মধ্যে দশমিকের পরে ২টি।
python
Copy
MinValueValidator(Decimal("0.00"))
Admin বা Django form দিয়ে তথ্য যাচাই করার সময় ঋণাত্মক দাম গ্রহণ করবে না।
Model-এর save() সরাসরি চালালে সব validator স্বয়ংক্রিয়ভাবে চলে না। পরবর্তী সময়ে API বা অন্য write path তৈরি করলে validation এবং প্রয়োজনমতো database constraint-ও যোগ করতে হবে।
auto_now_add=True
রেকর্ড প্রথম তৈরি হওয়ার সময় Django নিজে সময় বসাবে।
ordering
python
Copy
ordering = ["-created_at", "-pk"]
নতুন রেকর্ড আগে দেখাবে। pk হলো primary key—সাধারণত Django-এর তৈরি unique ID।
__str__
Admin-এ কোর্সকে শুধু Course object (1) না দেখিয়ে কোর্সের নাম দেখায়।
১২.
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:43 AM
m
You
Continue
•
12:44 AM
GPT 6 Astra
GPT 6 Astra
এবার আমরা Admin Panel, যোগাযোগ ফর্ম, তিনটি পেজ এবং ডিজাইন তৈরি করে সাইট চালু করব।
কাজের নিয়ম: নিচে কোনো ফাইলের সম্পূর্ণ কোড দিলে, সেই ফাইলের আগের কোড সরিয়ে নতুন কোড বসাবে। config/settings.py-এর ক্ষেত্রে আগের ধাপে করা পরিবর্তনগুলো রেখো।
১২. Admin Panel প্রস্তুত করো
Django-এর built-in Admin Panel থেকে কোর্স যোগ করা এবং যোগাযোগের মেসেজ দেখা যাবে।
খোলো:
text
Copy
core/admin.py
কোড দাও:
python
Copy
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", "description")
readonly_fields = ("created_at",)
@admin.register(ContactMessage)
class ContactMessageAdmin(admin.ModelAdmin):
list_display = ("name", "email", "created_at")
search_fields = ("name", "email", "message")
readonly_fields = ("name", "email", "message", "created_at")
def has_add_permission(self, request):
return False
admin.site.site_header = "EduShop প্রশাসন"
admin.site.site_title = "EduShop Admin"
admin.site.index_title = "ওয়েবসাইট পরিচালনা"
ব্যাখ্যা
@admin.register(Course): Course model-কে Admin Panel-এ যুক্ত করে।
list_display: তালিকায় কোন কলামগুলো দেখাবে।
list_filter: পাশ থেকে তথ্য filter করার ব্যবস্থা।
search_fields: কোন field দিয়ে search করা যাবে।
readonly_fields: যেসব তথ্য Admin-এ পরিবর্তন করা যাবে না।
has_add_permission: Admin থেকে যোগাযোগের মেসেজ তৈরি বন্ধ করেছি। মেসেজ আসবে ওয়েবসাইটের যোগাযোগ ফর্ম থেকে।
Admin ব্যবহারকারী চাইলে মেসেজ পড়তে ও মুছে ফেলতে পারবে।
১৩. যোগাযোগের Form তৈরি করো
খোলো বা তৈরি করো:
text
Copy
core/forms.py
কোড দাও:
python
Copy
from django import forms
from .models import ContactMessage
class ContactForm(forms.ModelForm):
class Meta:
model = ContactMessage
fields = ["name", "email", "message"]
widgets = {
"name": forms.TextInput(
attrs={
"placeholder": "তোমার নাম",
"autocomplete": "name",
}
),
"email": forms.EmailInput(
attrs={
"placeholder": "name@example.com",
"autocomplete": "email",
}
),
"message": forms.Textarea(
attrs={
"placeholder": "কী জানতে চাও?",
"rows": 6,
}
),
}
def clean_message(self):
message = self.cleaned_data["message"]
if len(message) < 10:
raise forms.ValidationError(
"মেসেজটি কমপক্ষে ১০ অক্ষরের হতে হবে।"
)
return message
ব্যাখ্যা
ModelForm একটি model থেকে form বানাতে পারে।
python
Copy
model = ContactMessage
মানে এই form-এর তথ্য ContactMessage model অনুযায়ী হবে।
python
Copy
fields = ["name", "email", "message"]
স্পষ্টভাবে বলেছি, ব্যবহারকারী শুধু এই তিনটি field জমা দিতে পারবে। created_at নিজে থেকে বসবে।
widgets দিয়ে HTML input-এর ধরন ও বৈশিষ্ট্য ঠিক করছি।
clean_message() হলো অতিরিক্ত validation। মেসেজ ১০ অক্ষরের কম হলে গ্রহণ করবে না। Model-এর max_length=2000 অনুযায়ী সর্বোচ্চ দৈর্ঘ্যও form যাচাই করবে।
শুধু browser-এর validation যথেষ্ট নয়। Django server-এ আবার তথ্য যাচাই করবে।
১৪. তিনটি View তৈরি করো
খোলো:
text
Copy
core/views.py
কোড দাও:
python
Copy
from django.contrib import messages
from django.shortcuts import redirect, render
from django.views.decorators.http import require_http_methods, require_safe
from .forms import ContactForm
from .models import Course
@require_safe
def home(request):
featured_courses = Course.objects.filter(is_published=True)[:3]
return render(
request,
"core/home.html",
{"featured_courses": featured_courses},
)
@require_safe
def courses(request):
published_courses = Course.objects.filter(is_published=True)
return render(
request,
"core/courses.html",
{"courses": published_courses},
)
@require_http_methods(["GET", "POST"])
def contact(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
form.save()
messages.success(
request,
"তোমার মেসেজ সফলভাবে জমা হয়েছে। ধন্যবাদ!",
)
return redirect("core:contact")
else:
form = ContactForm()
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:44 AM
m
You
Continue
•
12:44 AM
GPT 6 Astra
GPT 6 Astra
আগের উত্তরে core/views.py-এর কোড অসম্পূর্ণ ছিল। প্রথমে ওই ফাইলের পুরো কোড নিচেরটি দিয়ে বদলে দাও। এরপর বাকি ফাইলগুলো তৈরি করে সাইট চালাব।
১৪. View-এর সম্পূর্ণ কোড
ফাইল:
text
Copy
core/views.py
python
Copy
from django.contrib import messages
from django.shortcuts import redirect, render
from django.views.decorators.http import require_http_methods, require_safe
from .forms import ContactForm
from .models import Course
@require_safe
def home(request):
featured_courses = Course.objects.filter(is_published=True)[:3]
return render(
request,
"core/home.html",
{"featured_courses": featured_courses},
)
@require_safe
def courses(request):
published_courses = Course.objects.filter(is_published=True)
return render(
request,
"core/courses.html",
{"courses": published_courses},
)
@require_http_methods(["GET", "POST"])
def contact(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
form.save()
messages.success(
request,
"তোমার মেসেজ সফলভাবে জমা হয়েছে। ধন্যবাদ!",
)
return redirect("core:contact")
else:
form = ContactForm()
return render(
request,
"core/contact.html",
{"form": form},
)
কীভাবে কাজ করে?
ডেটাবেস থেকে কোর্স আনা
python
Copy
Course.objects.filter(is_published=True)
শুধু প্রকাশিত কোর্স আনে। লুকানো কোর্স দর্শকের পেজে দেখাবে না।
python
Copy
[:3]
হোম পেজে সর্বোচ্চ তিনটি কোর্স দেখায়।
Template-এ তথ্য পাঠানো
python
Copy
{"courses": published_courses}
এখানে বাম পাশের "courses" নামটি দিয়ে HTML template-এ তথ্য ব্যবহার করব।
যোগাযোগ ফর্ম
GET request: খালি form দেখায়।
POST request: জমা দেওয়া তথ্য যাচাই করে।
form.is_valid(): তথ্য বৈধ কি না দেখে।
form.save(): বৈধ তথ্য ডেটাবেসে সংরক্ষণ করে।
redirect(): সফল submission-এর পরে নতুন GET request-এ নিয়ে যায়।
শেষের পদ্ধতিকে Post/Redirect/Get বলা হয়। এতে সফল submission-এর পরে browser refresh করলে একই POST আবার জমা পড়ার সাধারণ সমস্যাটি এড়ানো যায়।
ভুল তথ্য দিলে redirect হবে না; একই পেজে error-সহ form দেখাবে।
১৫. URL যুক্ত করো
১৫.১ App-এর URL
ফাইল তৈরি বা খোলো:
text
Copy
core/urls.py
python
Copy
from django.urls import path
from . import views
app_name = "core"
urlpatterns = [
path("", views.home, name="home"),
path("courses/", views.courses, name="courses"),
path("contact/", views.contact, name="contact"),
]
ব্যাখ্যা
python
Copy
path("courses/", views.courses, name="courses")
এর অর্থ:
/courses/ ঠিকানায় request এলে
views.courses চালাও
এই URL-এর নাম রাখো courses
app_name = "core" থাকায় URL-টিকে core:courses নামে উল্লেখ করতে পারব। ভবিষ্যতে অন্য app-এর একই নামের URL থাকলেও বিভ্রান্তি কমবে।
১৫.২ Project-এর মূল URL
ফাইল:
text
Copy
config/urls.py
পুরো কোড বদলে দাও:
python
Copy
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("core.urls")),
]
include("core.urls") আমাদের app-এর URL-গুলো মূল project-এর সঙ্গে যুক্ত করছে।
১৬. সব পেজের সাধারণ কাঠামো
তিনটি পেজেই header, menu ও footer থাকবে। সেগুলো বারবার না লিখে একটি base template বানাব।
ফাইল:
text
Copy
templates/base.html
html
Code
Preview
Copy
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:45 AM
m
You
Continue
•
12:45 AM
GPT 6 Astra
GPT 6 Astra
আগের উত্তরে base.html-এর কোড মাঝপথে থেমে গেছে। ওই ফাইলের অসম্পূর্ণ কোড মুছে নিচের সম্পূর্ণ কোড বসাও। এবার বাকি ফাইলগুলো শেষ করে ওয়েবসাইট চালু করব।
প্রতিটি ফাইল লেখার পরে Ctrl + S দিয়ে save করবে। PowerShell command চালাবে djnagosite ফোল্ডারে, যেখানে manage.py আছে।
১৬. Base template-এর সম্পূর্ণ কোড
ফাইল:
text
Copy
templates/base.html
html
Code
Preview
Copy
ব্যাখ্যা
Static file যুক্ত করা
django
Copy
{% load static %}
Django-এর static template tag ব্যবহার করার সুযোগ দেয়।
django
Copy
{% static 'css/style.css' %}
CSS ফাইলের URL তৈরি করে। এটি Windows-এর filesystem path নয়।
Template block
django
Copy
{% block content %}
{% endblock %}
এখানে প্রতিটি পেজ নিজের আলাদা কনটেন্ট বসাবে। Header ও footer একই থাকবে।
Named URL
django
Copy
{% url 'core:courses' %}
আগের ধাপে দেওয়া URL-এর নাম দিয়ে লিংক তৈরি করে। পরে URL path বদলালেও template-এ সরাসরি /courses/ খুঁজে বদলাতে হবে না।
Messages
django
Copy
{{ message }}
যোগাযোগ ফর্ম সফলভাবে জমা দেওয়ার পরে Django-এর success message দেখাবে।
সক্রিয় menu
html
Code
Preview
Copy
বর্তমান পেজের লিংক চিহ্নিত করে। CSS দিয়ে সেটিকে আলাদা রঙ দেব।
১৭. হোম পেজ তৈরি করো
ফাইল:
text
Copy
templates/core/home.html
html
Code
Preview
Copy
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:45 AM
m
You
Continue
•
12:46 AM
GPT 6 Astra
GPT 6 Astra
আগের উত্তরে হোম পেজের কোড অসম্পূর্ণ ছিল। templates/core/home.html ফাইলের সব কোড মুছে নিচের সম্পূর্ণ কোড বসাও। এবার বাকি পেজ, CSS, database ও Admin setup শেষ করে সাইট চালু করব।
এই অংশে নতুন করে project তৈরি করবে না। আগের ধাপের ফাইলগুলোই ব্যবহার করবে। প্রতিটি ফাইল save করবে এবং PowerShell command চালাবে manage.py থাকা djnagosite ফোল্ডারে।
১৭. হোম পেজের সম্পূর্ণ কোড
ফাইল:
text
Copy
templates/core/home.html
html
Code
Preview
Copy
ব্যাখ্যা
django
Copy
{% extends "base.html" %}
হোম পেজ base.html-এর header, footer ও সাধারণ কাঠামো ব্যবহার করছে।
django
Copy
{% for course in featured_courses %}
View থেকে পাঠানো featured_courses তালিকার প্রতিটি কোর্স দেখায়।
django
Copy
{{ course.title }}
একটি কোর্সের নাম দেখায়।
django
Copy
{{ course.description|truncatewords:25 }}
বিবরণ বড় হলে সংক্ষেপে প্রথম ২৫টি শব্দ পর্যন্ত দেখায়।
django
Copy
{% empty %}
কোনো কোর্স না থাকলে বিকল্প লেখা দেখায়। তাই প্রথমবার database খালি থাকলেও পেজ কাজ করবে।
১৮. কোর্সের পেজ তৈরি করো
ফাইল:
text
Copy
templates/core/courses.html
html
Code
Preview
Copy
গুরুত্বপূর্ণ বিষয়
django
Copy
{{ course.description|linebreaksbr }}
Admin-এ বিবরণ লেখার সময় নতুন লাইন দিলে সেটি পেজেও দেখাবে।
Django template সাধারণভাবে variable-এর HTML escape করে। ব্যবহারকারীর দেওয়া তথ্য দেখানোর সময় অকারণে |safe ব্যবহার করবে না—এতে অনিরাপদ HTML চালু হয়ে
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:46 AM
m
You
Continue
•
12:47 AM
GPT 6 Astra
GPT 6 Astra
আগের কথাটির শেষ অংশ: ব্যবহারকারীর দেওয়া লেখা দেখাতে অকারণে |safe ব্যবহার করবে না—এতে ক্ষতিকর HTML বা JavaScript ঢুকে XSS vulnerability তৈরি হতে পারে। আমাদের বর্তমান template-এ এটি প্রয়োজন নেই।
এবার যোগাযোগ পেজ, CSS এবং database setup শেষ করি।
১৯. যোগাযোগ পেজ তৈরি করো
ফাইল:
text
Copy
templates/core/contact.html
সম্পূর্ণ কোড:
html
Code
Preview
Copy
ব্যাখ্যা
method="post"
ফর্মের তথ্য POST request-এর body-তে পাঠায়।
POST নিজে তথ্য encrypt করে না। লাইভ সাইটে নিরাপদ যোগাযোগের জন্য HTTPS প্রয়োজন।
{% csrf_token %}
Django-এর CSRF সুরক্ষার জন্য token যোগ করে। আগের default CsrfViewMiddleware চালু রেখো।
{{ form.as_div }}
Django form-এর label, input এবং validation error তৈরি করে। ভুল তথ্য জমা দিলে সংশ্লিষ্ট field-এর কাছে error দেখাবে।
এই form এখন শুধু database-এ মেসেজ সংরক্ষণ করে; কোনো email পাঠায় না। মেসেজ Admin Panel থেকে পড়বে।
২০. ওয়েবসাইটের CSS তৈরি করো
ফাইল:
text
Copy
static/css/style.css
সম্পূর্ণ কোড:
css
Copy
:root {
--primary: #1d4ed8;
--primary-dark: #1e40af;
--text: #172033;
--muted: #475569;
--border: #cbd5e1;
--background: #f8fafc;
--surface: #ffffff;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
font-family: system-ui, sans-serif;
line-height: 1.7;
color: var(--text);
background: var(--background);
overflow-wrap: anywhere;
}
a {
color: var(--primary);
text-underline-offset: 3px;
}
a:hover {
color: var(--primary-dark);
}
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
outline: 3px solid #7c3aed;
outline-offset: 4px;
}
h1,
h2,
h3 {
line-height: 1.35;
}
h1 {
font-size: clamp(2rem, 5vw, 3.3rem);
}
h2 {
font-size: 1.65rem;
}
p {
margin-top: 0;
}
.container {
width: min(1120px, 92%);
margin-inline: auto;
}
.main-content {
flex: 1;
padding-block: 32px 64px;
}
.site-header {
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.header-inner {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20px;
padding-block: 18px;
}
.brand {
font-size: 1.6rem;
font-weight: 800;
text-decoration: none;
}
.nav-links {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.nav-links a {
padding: 8px 12px;
border-radius: 8px;
color: var(--muted);
text-decoration: none;
font-weight: 600;
}
.nav-links a:hover,
.nav-links a[aria-current="page"] {
color: var(--primary);
background: #eff6ff;
}
.skip-link {
position: absolute;
top: 8px;
left: 8px;
transform: translateY(-180%);
z-index: 10;
padding: 10px 16px;
background: white;
border: 2px solid var(--primary);
}
.skip-link:focus {
transform: translateY(0);
}
.hero {
padding: clamp(28px, 6vw, 64px);
border: 1px solid #bfdbfe;
border-radius: 20px;
background: linear-gradient(135deg, #eff6ff, #eef2ff);
}
.hero h1 {
max-width: 780px;
margin-top: 12px;
}
.eyebrow {
color: var(--primary);
font-weight: 700;
}
.hero-description {
max-width: 680px;
font-size: 1.1rem;
color: var(--muted);
}
.button-row {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 24px;
}
.button {
display: inline-block;
padding: 11px 18px;
border: 1px solid var(--primary);
border-radius: 9px;
background: var(--primary);
color: white;
font: inherit;
font-weight: 600;
text-align: center;
text-decoration: none;
cursor:
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:47 AM
m
You
Continue
•
12:47 AM
GPT 6 Astra
GPT 6 Astra
আগের CSS কোডটি cursor: লাইনে থেমে গেছে। static/css/style.css ফাইলে ওই অসম্পূর্ণ cursor: লাইনটি মুছে নিচের কোড সেখান থেকে বসাও। আগের CSS রেখে দেবে।
css
Copy
cursor: pointer;
}
.button:hover {
background: var(--primary-dark);
border-color: var(--primary-dark);
color: white;
}
.button-secondary {
background: white;
color: var(--primary);
}
.button-secondary:hover {
background: #eff6ff;
color: var(--primary-dark);
}
.section {
margin-top: 48px;
}
.section-heading {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 20px;
}
.section-heading h2 {
margin: 0;
}
.card-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 20px;
}
.card {
min-width: 0;
padding: 24px;
border: 1px solid var(--border);
border-radius: 14px;
background: var(--surface);
box-shadow: 0 4px 16px rgb(15 23 42 / 4%);
}
.card h3 {
margin-top: 12px;
}
.card p,
.course-description {
color: var(--muted);
}
.course-card {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.course-card .button {
margin-top: auto;
}
.badge {
display: inline-block;
padding: 3px 10px;
border-radius: 999px;
background: #dbeafe;
color: #1e40af;
font-size: 0.85rem;
font-weight: 700;
}
.card .price {
margin-block: 20px;
color: var(--primary);
font-size: 1.3rem;
font-weight: 800;
}
.empty-state {
grid-column: 1 / -1;
padding: 24px;
border: 1px dashed var(--border);
border-radius: 12px;
color: var(--muted);
background: white;
}
.page-heading {
max-width: 760px;
margin-bottom: 32px;
}
.page-heading h1 {
margin-block: 10px 16px;
}
.contact-panel {
max-width: 720px;
padding: 28px;
border: 1px solid var(--border);
border-radius: 14px;
background: var(--surface);
}
form > div {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 6px;
font-weight: 600;
}
input,
textarea {
width: 100%;
padding: 12px;
border: 1px solid #64748b;
border-radius: 8px;
background: white;
color: var(--text);
font: inherit;
}
textarea {
min-height: 160px;
resize: vertical;
}
input[aria-invalid="true"],
textarea[aria-invalid="true"] {
border-color: #b91c1c;
}
.errorlist {
margin-block: 8px;
padding-left: 24px;
color: #b91c1c;
}
.form-summary {
padding: 12px 16px;
border: 1px solid #fecaca;
border-radius: 8px;
background: #fef2f2;
color: #991b1b;
}
.helptext {
display: block;
margin-top: 6px;
color: var(--muted);
font-size: 0.9rem;
}
.notice {
padding: 14px 18px;
border: 1px solid #86efac;
border-radius: 10px;
background: #f0fdf4;
color: #166534;
}
.site-footer {
padding-block: 24px;
border-top: 1px solid var(--border);
background: white;
color: var(--muted);
text-align: center;
}
.site-footer p {
margin: 0;
}
@media (max-width: 900px) {
.card-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 600px) {
.header-inner {
flex-direction: column;
align-items: flex-start;
}
.card-grid {
grid-template-columns: 1fr;
}
.hero,
.contact-panel {
padding: 24px 18px;
}
.nav-links a {
padding: 8px 10px;
}
}
এতে বড় পর্দায় তিন কলাম, মাঝারি পর্দায় দুই কলাম এবং মোবাইলে এক কলামে card দেখাবে।
২১. Settings একবার যাচাই করো
খোলো:
text
Copy
config/settings.py
পুরো ফাইল বদলাবে না। নিচের বিষয়গুলো মিলিয়ে নাও।
২১.১ App registration
INSTALLED_APPS-এ Django-এর default app-গুলো রেখে "core" যোগ করা থাকতে হবে:
python
Copy
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"core",
]
আগে থেকেই "core.apps.CoreConfig" থাকলে সেটি রাখো; পাশাপাশি "core" আবার যোগ করবে না।
২১.২ Template folder
TEMPLATES-এর মধ্যে DIRS এমন হবে:
python
Copy
"DIRS": [BASE_DIR / "templates"],
একই configuration-এ এটি থাকবে:
python
Copy
"APP_DIRS": True,
Default context_processors-এ নিচেরগুলো রেখো:
python
Copy
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
এগুলো request, login-সং
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:47 AM
m
You
Continue
•
12:48 AM
GPT 6 Astra
GPT 6 Astra
এগুলো template-এ যথাক্রমে request-এর তথ্য, login-সংক্রান্ত তথ্য এবং success/error message ব্যবহার করতে সাহায্য করে।
এবার settings যাচাই শেষ করে সাইট চালু করি।
২১.৩ Static file-এর settings
config/settings.py-এ নিচের settings থাকবে:
python
Copy
STATIC_URL = "static/"
STATICFILES_DIRS = [
BASE_DIR / "static",
]
একই setting আগে থেকে থাকলে নতুন করে আবার লিখবে না; সেটি প্রয়োজনমতো ঠিক করবে।
এতে Django আমাদের এই ফাইলটি খুঁজে পাবে:
text
Copy
static/css/style.css
২১.৪ Middleware রেখে দাও
Default MIDDLEWARE-এর এই entry-গুলো সরাবে না:
python
Copy
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
এগুলো session, CSRF protection, authentication এবং messages-এর জন্য প্রয়োজন। উপরের তালিকা দিয়ে পুরো MIDDLEWARE বদলাবে না—বাকি default entry-গুলোও রেখো।
২২. ফাইলের কাঠামো মিলিয়ে নাও
প্রয়োজনীয় ফাইলগুলো এমন জায়গায় থাকবে:
text
Copy
djnagosite/
├── manage.py
├── config/
│ ├── settings.py
│ └── urls.py
├── core/
│ ├── migrations/
│ ├── admin.py
│ ├── forms.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── templates/
│ ├── base.html
│ └── core/
│ ├── home.html
│ ├── courses.html
│ └── contact.html
└── static/
└── css/
└── style.css
এখানে শুধু প্রয়োজনীয় অংশ দেখানো হয়েছে। অন্য default ফাইলগুলো মুছবে না।
২৩. Database table তৈরি করো
PowerShell-এ manage.py থাকা ফোল্ডারে যাও। আগের ধাপে তৈরি virtual environment সক্রিয় আছে কি না নিশ্চিত হও।
প্রথমে চালাও:
powershell
Copy
python manage.py check
কোনো সমস্যা না পেলে সাধারণত দেখাবে:
text
Copy
System check identified no issues (0 silenced).
এরপর:
powershell
Copy
python manage.py makemigrations core
python manage.py migrate
কোন command কী করে?
makemigrations core: model-এর পরিবর্তন থেকে migration file তৈরি করে।
migrate: migration অনুযায়ী database-এর table তৈরি বা পরিবর্তন করে।
আগে migration তৈরি করা থাকলে No changes detected দেখানো স্বাভাবিক।
কোনো command-এ error হলে আগে সেটি ঠিক করবে; error উপেক্ষা করে পরের command চালাবে না।
২৪. Admin ব্যবহারকারী তৈরি করো
চালাও:
powershell
Copy
python manage.py createsuperuser
তারপর terminal-এর নির্দেশনা অনুযায়ী username, email এবং password দাও।
Password টাইপ করার সময় terminal-এ অক্ষর বা তারকা না দেখানো স্বাভাবিক। Password লিখে Enter চাপবে।
শক্তিশালী ও আলাদা password ব্যবহার করো।
২৫. Development server চালাও
চালাও:
powershell
Copy
python manage.py runserver
Server চালু থাকলে browser-এ খোলো:
text
Copy
http://127.0.0.1:8000/
এখন এই ঠিকানাগুলো দেখতে পারবে:
পেজ ঠিকানা
হোম http://127.0.0.1:8000/
কোর্স http://127.0.0.1:8000/courses/
যোগাযোগ http://127.0.0.1:8000/contact/
Admin http://127.0.0.1:8000/admin/
Server বন্ধ করতে terminal-এ চাপবে:
text
Copy
Ctrl + C
এটি এখন তোমার কম্পিউটারে চলা local website—ইন্টারনেটে প্রকাশিত live site নয়।
২৬. Admin থেকে কোর্স যোগ করো
১. /admin/ ঠিকানায় যাও।
২. তৈরি করা superuser দিয়ে login করো।
৩. Courses-এর পাশে Add চাপো।
৪. কোর্সের তথ্য দাও।
উদাহরণ:
text
Copy
Title: Python শেখার শুরু
Description:
এই কোর্সে Python-এর variable, condition, loop ও function শেখানো হবে।
ছোট প্রজেক্টের মাধ্যমে অনুশীলন করা হবে।
Price: 1500.00
Is published: চালু
৫. Save চাপো।
৬. কোর্সের পেজ refresh করো।
কোর্সটি এখন দেখা যাওয়ার কথা। Is published বন্ধ করে save করলে public page-এ আর দেখাবে না।
নতুন কোর্স আগে দেখানোর ছোট সংশোধন
হোম পেজে আমরা “নতুন কোর্স” লিখেছি। সেটি নিশ্চিত করতে core/views.py-এর সংশ্লিষ্ট query দুটো এভাবে লিখতে পারো:
home()-এর মধ্যে:
python
Copy
featured_courses = Course.objects.filter(
is_published=True
).order_by("-created_at", "-pk")[:3]
courses()-এর মধ্যে:
python
Copy
published_courses = Course.objects.filter(
is_published=True
).order_by("-created_at", "-pk")
এতে সর্বশেষ তৈরি কোর্স আগে আসবে। এখানে শুধু query বদলাবে; view-এর বাকি কোড রাখবে।
২৭. যোগাযোগ ফর্ম পরীক্ষা করো
যোগাযোগ পেজে গিয়ে নাম, email ও অন্তত ১০ অক্ষরের একটি মেসেজ দিয়ে submit করো।
উদাহরণ:
text
Copy
নাম: পরীক্ষামূলক ব্যবহারকারী
ইমেইল: learner@example.com
মেসেজ: Python কোর্স সম্পর্কে বিস্তারিত জানতে চাই।
সফল হলে confirmation message দেখাবে।
এরপর Admin Panel-এর Contact messages তালিকায় গিয়ে মেসেজটি দেখো।
এই পরীক্ষাগুলোও করো
নাম খালি রেখে submit করার চেষ্টা।
ভুল email দিয়ে submit করার চেষ্টা।
১০ অক্ষরের কম মেসেজ পাঠানো।
সঠিক
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:49 AM
m
You
Continue
•
12:49 AM
GPT 6 Astra
GPT 6 Astra
সঠিক তথ্য দিয়ে submit করে success message দেখা।
সফল submission-এর পরে পেজ refresh করে নতুন মেসেজ আবার জমা হচ্ছে কি না দেখা।
Admin Panel-এ সংরক্ষিত তথ্য ঠিক আছে কি না যাচাই করা।
ছোট স্পষ্টীকরণ: মেসেজের “কমপক্ষে ১০ অক্ষর” নিয়মটি তখনই কার্যকর হবে, যখন আগের ContactForm বা model-এ সেই validation লেখা আছে। শুধু HTML template এই নিয়ম তৈরি করে না।
২৮. ছোট মেসেজ আটকানোর validation
যদি আগের ContactForm-এ এই validation না থাকে, তাহলে core/forms.py-এ বিদ্যমান ContactForm class-এর ভেতরে নিচের method যোগ করো।
ফাইলের উপরে এই import থাকতে হবে:
python
Copy
from django import forms
Class-এর ভেতরে যোগ করবে:
python
Copy
def clean_message(self):
message = self.cleaned_data.get("message", "").strip()
if len(message) < 10:
raise forms.ValidationError(
"মেসেজে অন্তত ১০টি অক্ষর লিখো।"
)
return message
খেয়াল রাখবে:
এখানে form field-এর নাম message ধরে নেওয়া হয়েছে।
clean_message() আগে থেকেই থাকলে নতুন আরেকটি তৈরি না করে আগেরটি সংশোধন করো।
এটি ContactForm class-এর method হবে, Meta class-এর ভেতরে নয়।
শুধু form validation পরিবর্তন করলে database migration প্রয়োজন নেই।
এবার ছোট মেসেজ পাঠালে error দেখাবে এবং বৈধ না হওয়ায় view সেটি save করবে না।
২৯. কোর্সের ordering নিয়ে একটি যাচাই
আগের ধাপে ব্যবহার করেছিলাম:
python
Copy
.order_by("-created_at", "-pk")
এটি কাজ করতে Course model-এ created_at field থাকতে হবে।
ওই field না থাকলে, আপাতত query দুটো এভাবে লিখতে পারো:
home()-এর মধ্যে:
python
Copy
featured_courses = (
Course.objects
.filter(is_published=True)
.order_by("-pk")[:3]
)
courses()-এর মধ্যে:
python
Copy
published_courses = (
Course.objects
.filter(is_published=True)
.order_by("-pk")
)
Default auto-increment primary key ব্যবহার করলে এতে সাধারণভাবে পরে যোগ করা কোর্স আগে আসবে। তবে এটি প্রকৃত creation timestamp দিয়ে সাজানোর বিকল্প নয়।
৩০. সাধারণ error ও সমাধান
৩০.১ TemplateDoesNotExist
যেমন:
text
Copy
TemplateDoesNotExist: core/home.html
যাচাই করো ফাইলটি এখানে আছে কি না:
text
Copy
templates/core/home.html
এবং config/settings.py-এর TEMPLATES-এ:
python
Copy
"DIRS": [BASE_DIR / "templates"],
ফাইলের নাম ভুল করে home.html.txt হয়ে গেছে কি না-ও দেখো।
৩০.২ CSS দেখা যাচ্ছে না
প্রথমে নিশ্চিত হও:
text
Copy
static/css/style.css
ফাইলটি আছে।
তারপর terminal-এ চালাও:
powershell
Copy
python manage.py findstatic css/style.css
পাওয়া গেলে Django ফাইলটির অবস্থান দেখাবে।
এরপর browser-এ hard refresh করো:
text
Copy
Ctrl + F5
লোকাল development-এ DEBUG = True এবং django.contrib.staticfiles চালু থাকলে runserver সাধারণত static file serve করে। লাইভ সাইটে একই ব্যবস্থা ব্যবহার করা যাবে না।
৩০.৩ no such table: core_course
সাধারণত database migration প্রয়োগ করা হয়নি।
চালাও:
powershell
Copy
python manage.py makemigrations core
python manage.py migrate
Migration-এর অবস্থা দেখতে:
powershell
Copy
python manage.py showmigrations core
প্রয়োগ করা migration-এর পাশে [X] দেখাবে।
৩০.৪ Admin-এ Courses দেখা যাচ্ছে না
core/admin.py-এ Course register করা আছে কি না দেখো।
আগে register করা না থাকলে সর্বনিম্ন কোড:
python
Copy
from django.contrib import admin
from .models import Course
admin.site.register(Course)
আগে থেকেই @admin.register(Course) বা admin.site.register(Course) থাকলে আবার register করবে না। বিদ্যমান অন্য model registration-ও মুছবে না।
যোগাযোগের মেসেজ দেখতে সেটির model-ও Admin-এ register থাকতে হবে।
৩০.৫ CSRF verification failed
নিশ্চিত হও form-এর ভেতরে আছে:
django
Copy
{% csrf_token %}
এবং default CSRF middleware চালু আছে।
Admin login করার পরে পুরোনো খোলা form submit করলে token বদলের কারণে এমন হতে পারে। যোগাযোগ পেজ reload করে আবার চেষ্টা করো।
এটি ঠিক করতে @csrf_exempt যোগ করে সুরক্ষা বন্ধ করবে না।
৩০.৬ Port আগে থেকেই ব্যবহার হচ্ছে
অন্য port-এ চালাও:
powershell
Copy
python manage.py runserver 8001
তারপর খোলো:
text
Copy
http://127.0.0.1:8001/
৩১. শেষবারের মতো পরীক্ষা
পরীক্ষা প্রত্যাশিত ফল
হোম পেজ খোলা Header, hero, course card ও footer দেখা
কোর্সের পেজ খোলা শুধু প্রকাশিত কোর্স দেখা
কোর্স unpublished করা Public page থেকে কোর্সটি সরে যাওয়া
সঠিক যোগাযোগ ফর্ম জমা Success message এবং database-এ রেকর্ড
ভুল তথ্য জমা Validation error; নতুন রেকর্ড না হওয়া
সফল submission-এর পরে refresh সাধারণ refresh-এ একই POST আবার না হওয়া
Browser ছোট করা Card এক কলামে চলে আসা
কিবোর্ডে Tab চাপা Link ও form control-এ দৃশ্যমান focus
Post/Redirect/Get সাধারণ refresh-
You ran out of credits
This answer stopped because it used up your remaining credits. Your progress is saved, so you can pick up right where it left off. Upgrade
•
12:50 AM
m
You
Continue
•
12:50 AM
GPT 6 Astra
GPT 6 Astra
Post/Redirect/Get সাধারণ refresh-এর সময় একই form আবার submit হওয়া ঠেকায়। তবে দ্রুত দুবার submit করা বা একই request পুনরায় পাঠানোর সব পরিস্থিতি এটি আটকায় না।
এবার শেষ কয়েকটি বিষয় মিলিয়ে নিই।
৩২. সফল submission-এর পরে redirect নিশ্চিত করো
যোগাযোগ form বৈধ হলে view-এর কাজের ক্রম হবে:
মেসেজ save করা।
Success message যোগ করা।
যোগাযোগ পেজে redirect করা।
আগের ContactForm যদি ModelForm হয়, তাহলে core/views.py-এর contact() view এমন হতে পারে:
python
Copy
from django.contrib import messages
from django.shortcuts import redirect, render
from .forms import ContactForm
def contact(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
form.save()
messages.success(
request,
"তোমার মেসেজ জমা হয়েছে। ধন্যবাদ!",
)
return redirect("core:contact")
else:
form = ContactForm()
return render(
request,
"core/contact.html",
{"form": form},
)
পুরো views.py এই কোড দিয়ে বদলাবে না। বিদ্যমান home() ও courses() রাখবে। প্রয়োজন হলে শুধু contact() সংশোধন করবে এবং অনুপস্থিত import যোগ করবে।
ContactForm যদি সাধারণ forms.Form হয়, তাহলে সরাসরি form.save() কাজ করবে না। সে ক্ষেত্রে আগের view-এর database-এ save করার কোড রাখবে।
ভুল তথ্য দিলে কী হবে?
form.is_valid() মিথ্যা হলে redirect হবে না। একই bound form template-এ ফেরত যাবে, যাতে ব্যবহারকারী নিজের লেখা এবং সংশ্লিষ্ট error দেখতে পারে।
৩৩. পরের দিন আবার সাইট চালু করবে যেভাবে
প্রতিবার নতুন করে project, migration বা superuser তৈরি করতে হবে না।
১. PowerShell খুলে manage.py থাকা ফোল্ডারে যাও।
২. আগের virtual environment সক্রিয় করো। যেমন, সেটির নাম .venv হলে:
powershell
Copy
.\.venv\Scripts\Activate.ps1
তোমার environment-এর নাম অন্য হলে সেই নাম ব্যবহার করবে।
৩. Server চালাও:
powershell
Copy
python manage.py runserver
৪. Browser-এ খোলো:
text
Copy
http://127.0.0.1:8000/
কখন কোন command লাগবে?
পরিবর্তন করণীয়
HTML বা CSS পরিবর্তন Save করে browser refresh
Python view বা form পরিবর্তন Save; development server সাধারণত reload করবে
Model-এর database field পরিবর্তন makemigrations, তারপর migrate
Server বন্ধ হয়ে গেছে আবার runserver
নতুন admin দরকার প্রয়োজন অনুযায়ী createsuperuser
নতুন ফাইল যোগ করার পর পরিবর্তন ধরা না পড়লে server বন্ধ করে আবার চালাও।
৩৪. Local project আর live website এক নয়
এখনকার setup শেখা ও local development-এর জন্য। ইন্টারনেটে প্রকাশ করার আগে অন্তত নিচের বিষয়গুলো ঠিক করতে হবে:
DEBUG = False করা।
নিজের domain অনুযায়ী ALLOWED_HOSTS নির্ধারণ করা।
SECRET_KEY ও অন্যান্য গোপন তথ্য environment variable-এ রাখা।
HTTPS চালু করা এবং প্রয়োজনমতো secure cookie settings করা।
runserver-এর বদলে production WSGI/ASGI server ব্যবহার করা।
Static file পরিবেশনের ব্যবস্থা করা।
Database backup রাখা।
যোগাযোগ form-এ spam ও অতিরিক্ত request নিয়ন্ত্রণের ব্যবস্থা করা।
Django ও dependency-গুলোর security update রাখা।
Production settings দিয়ে এই command চালিয়ে configuration-এর সতর্কতা পরীক্ষা করবে:
powershell
Copy
python manage.py check --deploy
এটি সহায়ক পরীক্ষা; পূর্ণ security audit নয়।
৩৫. এই ধাপে কী তৈরি হলো?
সব পরীক্ষা ঠিক থাকলে তোমার EduShop-এর প্রাথমিক সংস্করণ প্রস্তুত:
হোম পেজ।
Database থেকে প্রকাশিত কোর্সের তালিকা।
কোর্সের বিবরণ ও মূল্য।
Validation-সহ যোগাযোগ form।
Admin থেকে কোর্স পরিচালনা।
Admin থেকে যোগাযোগের মেসেজ দেখা।
মোবাইল উপযোগী layout।
এখনও course purchase, payment, শিক্ষার্থীর account বা lesson access তৈরি হয়নি। বর্তমান সংস্করণটি একটি course catalog ও যোগাযোগভিত্তিক ওয়েবসাইট।
পরের feature যোগ করার আগে হোম → কোর্স → যোগাযোগ → Admin—এই চারটি অংশ একবার পরীক্ষা করে নাও। কোনো error হলে terminal-এর সম্পূর্ণ error message এবং সংশ্লিষ্ট ফাইলের কোড পাঠাবে—password, SECRET_KEY বা ব্যক্তিগত তথ্য বাদ দিয়ে।