Django মাল্টিপল ডেটাবেস রাউটিং: শূন্য থেকে শুরু করে একটি পরিষ্কার প্রজেক্ট সেটআপ টিউটোরিয়াল
এই টিউটোরিয়ালে আমরা আপনার “Garments ERP” সিস্টেমের জন্য একটি নতুন Django প্রজেক্ট তৈরি করব এবং master_data, buyer, এবং product অ্যাপসগুলোকে তিনটি আলাদা SQLite ডেটাবেসে রাউট করব।
ধাপ ১: নতুন Django প্রজেক্ট এবং অ্যাপস তৈরি
প্রথমে আপনার কম্পিউটার থেকে একটি নতুন ফোল্ডার তৈরি করুন যেখানে আপনি প্রজেক্টটি রাখতে চান। এরপর সেই ফোল্ডারের ভিতরে টার্মিনাল বা কমান্ড প্রম্পট খুলে নিম্নলিখিত কমান্ডগুলো চালান:
# 1. একটি নতুন Django প্রজেক্ট তৈরি করুন
django-admin startproject garments_erp_project
# 2. নতুন তৈরি হওয়া প্রজেক্ট ফোল্ডারের ভিতরে যান
cd garments_erp_project
# 3. প্রয়োজনীয় অ্যাপসগুলো তৈরি করুন
python manage.py startapp master_data
python manage.py startapp buyer
python manage.py startapp productধাপ ২: dbফোল্ডার তৈরি করুন
আপনার প্রজেক্টের রুট ডিরেক্টরিতে (যেখানে manage.py ফাইলটি আছে) db নামে একটি নতুন ফোল্ডার তৈরি করুন। আপনার SQLite ডেটাবেস ফাইলগুলো এই ফোল্ডারের ভিতরে তৈরি হবে।
# আপনার garments_erp_project ফোল্ডারের ভিতরে এই কমান্ডটি চালান
mkdir dbধাপ ৩: settings.pyকনফিগারেশন
আপনার garments_erp_project/settings.py ফাইলটি খুলুন এবং নিম্নলিখিত কোড দিয়ে আপডেট করুন। এটি আপনার অ্যাপস, ডেটাবেস এবং কাস্টম ইউজার মডেল কনফিগার করবে।
garments_erp_project/settings.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
# settings.py
import os
# BASE_DIR আপনার প্রজেক্টের রুট ডিরেক্টরি নির্দেশ করে
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# INSTALLED_APPS: আপনার প্রজেক্টে ব্যবহৃত সমস্ত অ্যাপস এখানে তালিকাভুক্ত করুন।
# master_data অ্যাপটি auth, admin, contenttypes, sessions এর পরে এবং আপনার অন্যান্য কাস্টম অ্যাপের আগে রাখুন।
# AUTH_USER_MODEL ব্যবহার করার কারণে এটি গুরুত্বপূর্ণ।
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# আপনার কাস্টম অ্যাপস
'master_data', # CustomUser মডেলের জন্য এটি আগে থাকা উচিত
'buyer',
'product',
]
# DATABASES: আপনার প্রজেক্টের জন্য ব্যবহৃত সমস্ত ডেটাবেস এখানে কনফিগার করুন।
# আমরা প্রতিটি অ্যাপের জন্য আলাদা SQLite ডেটাবেস ব্যবহার করছি।
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db', 'default.sqlite3'), # ডিফল্ট ডেটাবেস
},
'master_db': { # মাস্টার ডেটা যেমন Company, CustomUser
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db', 'master_data.sqlite3'),
},
'buyer_db': { # Buyer অ্যাপের ডেটা
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db', 'buyer_data.sqlite3'),
},
'product_db': { # ItemCategory, Item অ্যাপের ডেটা
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db', 'product_data.sqlite3'),
}
}
# AUTH_USER_MODEL: আপনার কাস্টম ইউজার মডেলটি master_data অ্যাপে সংজ্ঞায়িত হওয়ায়, Django কে তা জানিয়ে দিন।
AUTH_USER_MODEL = 'master_data.CustomUser'
# DATABASE_ROUTERS: আপনার কাস্টম ডেটাবেস রাউটার ক্লাসটি এখানে যোগ করুন।
# আমরা এটিকে garments_erp_project/routers.py ফাইলে তৈরি করব।
DATABASE_ROUTERS = ['garments_erp_project.routers.GlobalDataRouter']
# অন্যান্য সেটিংস (যেমন SECRET_KEY, ALLOWED_HOSTS ইত্যাদি) আপনার প্রয়োজন অনুযায়ী সেট করুন।
SECRET_KEY = 'django-insecure-your-secret-key' # এটি একটি র্যান্ডম স্ট্রিং দিয়ে প্রতিস্থাপন করুন
DEBUG = True
ALLOWED_HOSTS = []
# Static files (CSS, JavaScript, Images)
STATIC_URL = '/static/'
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'ধাপ ৪: routers.pyফাইল তৈরি এবং কনফিগারেশন
আপনার garments_erp_project ফোল্ডারের ভিতরে routers.py নামে একটি নতুন ফাইল তৈরি করুন এবং নিম্নলিখিত কোডটি যোগ করুন। এই ফাইলটি ডেটাবেস রাউটিংয়ের মূল লজিক ধারণ করে।
garments_erp_project/routers.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
# garments_erp_project/routers.py
class GlobalDataRouter:
"""
একটি ডেটাবেস রাউটার যা মডেলের উপর ভিত্তি করে ডেটাবেস অপারেশন নিয়ন্ত্রণ করে।
"""
route_app_labels = {
'auth': 'master_db', # <--- নিশ্চিত করুন এটি আছে
'admin': 'master_db', # <--- নিশ্চিত করুন এটি আছে
'contenttypes': 'master_db', # <--- নিশ্চিত করুন এটি আছে
'sessions': 'master_db', # <--- নিশ্চিত করুন এটি আছে
'master_data': 'master_db', # Company, CustomUser মডেল master_db তে যাবে
'buyer': 'buyer_db', # Buyer মডেল buyer_db তে যাবে
'product': 'product_db', # ItemCategory, Item মডেল product_db তে যাবে
}
def db_for_read(self, model, **hints):
"""
পড়ার (read) অপারেশনের জন্য কোন ডেটাবেস ব্যবহার করা হবে তা নির্ধারণ করে।
"""
if model._meta.app_label in self.route_app_labels:
return self.route_app_labels[model._meta.app_label]
return 'default' # অন্যান্য অ্যাপের জন্য ডিফল্ট ডেটাবেস (যদি থাকে)
def db_for_write(self, model, **hints):
"""
লেখার (write) অপারেশনের জন্য কোন ডেটাবেস ব্যবহার করা হবে তা নির্ধারণ করে।
"""
if model._meta.app_label in self.route_app_labels:
return self.route_app_labels[model._meta.app_label]
return 'default'
def allow_relation(self, obj1, obj2, **hints):
"""
দুটি মডেল ইনস্ট্যান্সের মধ্যে সম্পর্ক (ForeignKey, ManyToMany) অনুমোদিত কিনা তা নির্ধারণ করে।
"""
# যদি উভয় অবজেক্ট একই ডেটাবেসে থাকে, সম্পর্ক অনুমোদিত।
if obj1._state.db == obj2._state.db:
return True
# যদি master_db এর মডেলগুলো (যেমন CustomUser) default DB এর মডেলের সাথে সম্পর্ক রাখে
# (যদিও এখন auth, admin master_db তে যাচ্ছে, এটি ভবিষ্যতের ক্রস-DB সম্পর্কের জন্য সহায়ক)
if (obj1._state.db == 'master_db' and obj2._state.db == 'default') or \
(obj1._state.db == 'default' and obj2._state.db == 'master_db'):
return True
# অন্যান্য ক্রস-ডেটাবেস সম্পর্ক ডিফল্টভাবে অনুমোদিত নয়।
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
কোন ডেটাবেসে কোন অ্যাপের মডেল মাইগ্রেট করা যাবে তা নির্ধারণ করে।
"""
if app_label in self.route_app_labels:
# শুধুমাত্র নির্দিষ্ট ডেটাবেসে সংশ্লিষ্ট অ্যাপের মাইগ্রেশন অনুমোদিত।
return db == self.route_app_labels[app_label]
# যদি কোনো অ্যাপ route_app_labels এ না থাকে, তাহলে সেটি default ডেটাবেসে মাইগ্রেট হবে।
return db == 'default'
ধাপ ৫: মডেল ফাইল (models.py) তৈরি করুন
আপনার master_data, buyer, এবং product অ্যাপের models.py ফাইলগুলো নিম্নলিখিত কোড দিয়ে আপডেট করুন।
master_data/models.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
from django.db import models
from django.contrib.auth.models import AbstractUser, Group, Permission
class Company(models.Model):
company_code = models.CharField(max_length=20, unique=True, db_index=True, verbose_name="Company Code")
name = models.CharField(max_length=200, verbose_name="Company Name")
address = models.TextField(blank=True, verbose_name="Address")
phone = models.CharField(max_length=20, blank=True, verbose_name="Phone")
email = models.EmailField(blank=True, verbose_name="Email")
is_active = models.BooleanField(default=True, verbose_name="Is Active")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Company"
verbose_name_plural = "Companies"
def __str__(self):
return f"{self.company_code} - {self.name}"
class CustomUser(AbstractUser):
# CustomUser মডেলটি Company মডেলের সাথে ForeignKey ব্যবহার করছে,
# কারণ Company মডেলও master_db তে আছে।
company = models.ForeignKey(Company, on_delete=models.CASCADE, verbose_name="Company")
company_code = models.CharField(max_length=20, db_index=True, verbose_name="Company Code")
company_name = models.CharField(max_length=200, verbose_name="Company Name")
employee_id = models.CharField(max_length=50, blank=True, verbose_name="Employee ID")
phone = models.CharField(max_length=20, blank=True, verbose_name="Phone")
designation = models.CharField(max_length=100, blank=True, verbose_name="Designation")
is_company_owner = models.BooleanField(default=False, verbose_name="Is Company Owner")
# Django এর বিল্ট-ইন User মডেলের সাথে সংঘর্ষ এড়াতে unique related_name যোগ করুন
groups = models.ManyToManyField(
Group,
verbose_name=('groups'),
blank=True,
help_text=(
'The groups this user belongs to. A user will get all permissions '
'granted to each of their groups.'
),
related_name="custom_user_set",
related_query_name="custom_user",
)
user_permissions = models.ManyToManyField(
Permission,
verbose_name=('user permissions'),
blank=True,
help_text=('Specific permissions for this user.'),
related_name="custom_user_permissions_set",
related_query_name="custom_user",
)
class Meta:
verbose_name = "Custom User"
verbose_name_plural = "Custom Users"
def __str__(self):
return f"{self.username} ({self.company_name})"buyer/models.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
from django.db import models
class Buyer(models.Model):
# Company এর সাথে ForeignKey এর পরিবর্তে code/name ব্যবহার করা হয়েছে
# কারণ Company মডেল master_db তে আছে এবং Buyer মডেল buyer_db তে।
# এটি ক্রস-ডেটাবেস ForeignKey এড়াতে সাহায্য করে।
company_code = models.CharField(max_length=20, db_index=True, verbose_name="Company Code")
company_name = models.CharField(max_length=200, verbose_name="Company Name")
buyer_code = models.CharField(max_length=50, unique=True, db_index=True, verbose_name="Buyer Code")
name = models.CharField(max_length=200, verbose_name="Buyer Name")
country = models.CharField(max_length=100, blank=True, verbose_name="Country")
contact_person = models.CharField(max_length=100, blank=True, verbose_name="Contact Person")
phone = models.CharField(max_length=20, blank=True, verbose_name="Phone")
email = models.EmailField(blank=True, verbose_name="Email")
address = models.TextField(blank=True, verbose_name="Address")
is_active = models.BooleanField(default=True, verbose_name="Is Active")
# CustomUser এর সাথে ForeignKey এর পরিবর্তে employee_id/username ব্যবহার করা হয়েছে
# কারণ CustomUser মডেল master_db তে আছে এবং Buyer মডেল buyer_db তে।
created_by_employee_id = models.CharField(max_length=50, blank=True, verbose_name="Created By Employee ID")
created_by_username = models.CharField(max_length=150, blank=True, verbose_name="Created By Username")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Buyer"
verbose_name_plural = "Buyers"
unique_together = ('company_code', 'buyer_code')
def __str__(self):
return f"{self.buyer_code} - {self.name}"product/models.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
from django.db import models
class ItemCategory(models.Model):
# Company এর সাথে ForeignKey এর পরিবর্তে code/name
company_code = models.CharField(max_length=20, db_index=True, verbose_name="Company Code")
company_name = models.CharField(max_length=200, verbose_name="Company Name")
category_code = models.CharField(max_length=50, unique=True, db_index=True, verbose_name="Category Code")
name = models.CharField(max_length=200, verbose_name="Category Name")
description = models.TextField(blank=True, verbose_name="Description")
is_active = models.BooleanField(default=True, verbose_name="Is Active")
# CustomUser এর সাথে ForeignKey এর পরিবর্তে employee_id/username
created_by_employee_id = models.CharField(max_length=50, blank=True, verbose_name="Created By Employee ID")
created_by_username = models.CharField(max_length=150, blank=True, verbose_name="Created By Username")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Item Category"
verbose_name_plural = "Item Categories"
unique_together = ('company_code', 'category_code')
def __str__(self):
return f"{self.category_code} - {self.name}"
class Item(models.Model):
ITEM_TYPE_CHOICES = (
('fabric', 'Fabric'),
('trim', 'Trim'),
('accessory', 'Accessory'),
('finished_goods', 'Finished Goods'),
('raw_material', 'Raw Material'),
)
# Company এর সাথে ForeignKey এর পরিবর্তে code/name
company_code = models.CharField(max_length=20, db_index=True, verbose_name="Company Code")
company_name = models.CharField(max_length=200, verbose_name="Company Name")
item_code = models.CharField(max_length=50, unique=True, db_index=True, verbose_name="Item Code")
item_name = models.CharField(max_length=200, verbose_name="Item Name")
# ItemCategory এর সাথে ForeignKey এর পরিবর্তে code/name
category_code = models.CharField(max_length=50, db_index=True, verbose_name="Category Code")
category_name = models.CharField(max_length=200, verbose_name="Category Name")
item_type = models.CharField(max_length=20, choices=ITEM_TYPE_CHOICES, verbose_name="Item Type")
unit = models.CharField(max_length=20, verbose_name="Unit")
unit_price = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="Unit Price")
minimum_stock = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="Minimum Stock")
description = models.TextField(blank=True, verbose_name="Description")
is_active = models.BooleanField(default=True, verbose_name="Is Active")
# CustomUser এর সাথে ForeignKey এর পরিবর্তে employee_id/username
created_by_employee_id = models.CharField(max_length=50, blank=True, verbose_name="Created By Employee ID")
created_by_username = models.CharField(max_length=150, blank=True, verbose_name="Created By Username")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Item"
verbose_name_plural = "Items"
unique_together = ('company_code', 'item_code')
def __str__(self):
return f"{self.item_code} - {self.item_name}"ধাপ ৬: অ্যাডমিন প্যানেলে মডেল রেজিস্টার করুন (admin.py)
আপনার প্রতিটি অ্যাপের admin.py ফাইলগুলো নিম্নলিখিত কোড দিয়ে আপডেট করুন।
master_data/admin.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Company, CustomUser
# Company মডেল রেজিস্টার করুন
admin.site.register(Company)
# CustomUser মডেলকে UserAdmin ব্যবহার করে রেজিস্টার করুন
@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
fieldsets = UserAdmin.fieldsets + (
(('Company Info'), {'fields': ('company', 'company_code', 'company_name', 'employee_id', 'phone', 'designation', 'is_company_owner')}),
)
add_fieldsets = UserAdmin.add_fieldsets + (
(('Company Info'), {'fields': ('company', 'company_code', 'company_name', 'employee_id', 'phone', 'designation', 'is_company_owner')}),
)
list_display = ('username', 'email', 'company_name', 'employee_id', 'is_staff')
search_fields = ('username', 'email', 'company_name', 'employee_id')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups', 'company_name')buyer/admin.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
from django.contrib import admin
from .models import Buyer
# Register your models here.
admin.site.register(Buyer)product/admin.py ফাইলে নিচের কোডটি কপি করে পেস্ট করুন:
from django.contrib import admin
from .models import ItemCategory, Item
# Register your models here.
admin.site.register(ItemCategory)
admin.site.register(Item)ধাপ ৭: মাইগ্রেশন এবং সুপারইউজার তৈরি
এখন আপনার প্রজেক্টের রুট ডিরেক্টরিতে (যেখানে manage.py আছে) নিম্নলিখিত কমান্ডগুলো চালান:
- মাইগ্রেশন ফাইল তৈরি করুন:
এই কমান্ডটি আপনার সমস্ত অ্যাপের জন্য নতুন মাইগ্রেশন ফাইল তৈরি করবে।
python manage.py makemigrations- ডেটাবেস মাইগ্রেশন চালান (সঠিক ক্রমে):
এটি সবচেয়ে গুরুত্বপূর্ণ ধাপ।master_dbকে প্রথমে মাইগ্রেট করতে হবে, কারণauth,admin,contenttypes,sessionsএবং আপনারCompanyওCustomUserমডেল (যাmaster_dataঅ্যাপে আছে) এই ডেটাবেসে তৈরি হবে। এই কোর টেবিলগুলো ছাড়া Django Admin এবং ইউজার ম্যানেজমেন্ট কাজ করবে না।
# 1. master_db মাইগ্রেট করুন (auth, admin, contenttypes, sessions, master_data এর জন্য)
python manage.py migrate --database=master_db
# 2. buyer_db মাইগ্রেট করুন
python manage.py migrate --database=buyer_db
# 3. product_db মাইগ্রেট করুন
python manage.py migrate --database=product_db
# 4. default ডেটাবেস মাইগ্রেট করুন (যদি default ডেটাবেসে কোনো অ্যাপ থাকে যা route_app_labels এ নেই)
# এই সেটআপে default ডেটাবেস সাধারণত খালি থাকবে, তবে এটি চালানো নিরাপদ।
python manage.py migrate --database=default- সুপারইউজার তৈরি করুন (
master_dbনির্দিষ্ট করে):
যেহেতুCustomUserমডেলটিmaster_dbতে আছে, তাই সুপারইউজারও সেখানেই তৈরি করতে হবে।
python manage.py createsuperuser --database=master_dbপ্রম্পট অনুযায়ী ইউজারনেম, ইমেইল এবং পাসওয়ার্ড দিন।
- সার্ভার চালান:
python manage.py runserver- Django Admin অ্যাক্সেস করুন:
আপনার ব্রাউজারেhttp://127.0.0.1:8000/admin/এ যান এবং আপনার তৈরি করা সুপারইউজার ক্রেডেনশিয়াল দিয়ে লগইন করুন। এখন আপনিCompany,CustomUser,Buyer,ItemCategory, এবংItemমডেলগুলো অ্যাডমিন প্যানেলে দেখতে এবং CRUD অপারেশন করতে পারবেন।
এই টিউটোরিয়ালটি আপনাকে একটি সম্পূর্ণ নতুন এবং পরিষ্কার Django প্রজেক্ট সেটআপ করতে সাহায্য করবে, যেখানে মাল্টিপল ডেটাবেস রাউটিং সঠিকভাবে কনফিগার করা হয়েছে।
পরবর্তী পদক্ষেপ:
- আরও অ্যাপ যোগ করুন: অর্ডার ম্যানেজমেন্ট, প্রোডাকশন, ইনভেন্টরি ইত্যাদির মতো অতিরিক্ত ERP মডিউল যোগ করুন।
- API এন্ডপয়েন্ট তৈরি করুন: Django REST Framework ব্যবহার করে মডেলগুলির জন্য API এন্ডপয়েন্ট তৈরি করুন।
- রিয়েল-টাইম স্টক হ্যান্ডলিং প্রয়োগ করুন: WebSockets ব্যবহার করে রিয়েল-টাইম স্টক হ্যান্ডলিং কার্যকারিতা যোগ করুন।
- ক্যাশিং কৌশল যোগ করুন: ঘন ঘন অ্যাক্সেস করা ডেটার জন্য একটি ক্যাশিং কৌশল প্রয়োগ করুন।