دوره‌ها / Django / به‌روزرسانی مدل (Update Model)

به‌روزرسانی مدل (Update Model)

30 دقیقه Article

به‌روزرسانی مدل: تغییر ساختار دیتابیس 🔧

در دنیای واقعی، نیازهای پروژه تغییر می‌کنه و باید مدل‌ها رو آپدیت کنیم. جنگو با سیستم Migration این کار رو خیلی راحت کرده!

Migration چیست؟ Migration فایل‌های پایتونی هستن که تغییرات دیتابیس رو توصیف می‌کنن. اون‌ها مثل نسخه‌های کنترل شده برای دیتابیس هستن که می‌تونید به جلو و عقب برید.

مراحل آپدیت مدل

وقتی یک مدل رو تغییر می‌دید، این مراحل رو دنبال کنید:

# 1. ساخت مایگریت بعد از تغییر مدل
python manage.py makemigrations

# 2. مشاهده SQL که اجرا میشه (بدون اعمال)
python manage.py sqlmigrate blog 0002

# 3. اعمال مایگریت
python manage.py migrate

# 4. برگشت به مایگریت قبلی (در صورت نیاز)
python manage.py migrate blog 0001

مثال: اضافه کردن فیلد جدید

فرض کنید می‌خواید یک فیلد views به مدل Post اضافه کنید:

# blog/models.py
class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    views = models.IntegerField(default=0)  # فیلد جدید
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title

خروجی makemigrations:

جنگو یک فایل مایگریت می‌سازه که این تغییرات رو توصیف می‌کنه:

# blog/migrations/0002_post_views.py
from django.db import migrations, models

class Migration(migrations.Migration):
    dependencies = [
        ('blog', '0001_initial'),
    ]
    operations = [
        migrations.AddField(
            model_name='post',
            name='views',
            field=models.IntegerField(default=0),
        ),
    ]

تغییرات رایج مدل

  • اضافه کردن فیلد: فقط فیلد جدید رو اضافه کنید و default یا null=True بذارید
  • حذف فیلد: فیلد رو از مدل حذف کنید (داده‌ها از دست میره!)
  • تغییر نوع فیلد: نوع فیلد رو عوض کنید (ممکنه نیاز به تبدیل داده باشه)
  • اضافه کردن ForeignKey: فیلد ForeignKey رو اضافه کنید
هشدار مهم: اگر فیلدی رو حذف کنید، تمام داده‌های اون فیلد از دست میره! همیشه قبل از حذف، از داده‌ها backup بگیرید. همچنین، تغییر نوع فیلد ممکنه نیاز به تبدیل داده داشته باشه که باید دستی انجام بشه.

برگشت Migration (Rollback)

اگر اشتباهی migration رو اعمال کردید، می‌تونید به نسخه قبلی برگردید:

# برگشت به migration قبلی
python manage.py migrate blog 0001

# برگشت به migration خاص
python manage.py migrate blog 0002_post_views

# مشاهده وضعیت migrations
python manage.py showmigrations blog
نکته حرفه‌ای: همیشه migration ها رو در یک محیط تست اول امتحان کنید. همچنین، migration ها رو commit کنید تا تیم شما هم بتونن اون‌ها رو اجرا کنن.

🎯 تمرین عملی:

به مدل Post یک فیلد slug از نوع SlugField اضافه کنید. سپس migration رو بسازید، SQL اون رو ببینید و اعمالش کنید. بعد یک migration دیگه بسازید که فیلد slug رو unique=True کنه.

تمرین‌های عملی

برای تثبیت یادگیری این درس تمرین‌های زیر را حل کنید

تمرین: ساخت Migration سفارشی Hard
سوال تمرین

🎯 تمرین عملی: Migration پیشرفته

در این تمرین، یک migration سفارشی می‌سازیم که:

  1. یک فیلد جدید به مدل اضافه کنه
  2. داده‌های موجود رو به فیلد جدید migrate کنه
  3. یک تابع بنویسید که migration رو اعمال کنه

راهنمایی: از migrations.RunPython برای اجرای کد پایتون در migration استفاده کنید.

پاسخ تمرین
PYTHON
from django.db import migrations, models

def migrate_old_data(apps, schema_editor):
    # دسترسی به مدل در migration
    Post = apps.get_model('blog', 'Post')
    
    # تبدیل داده‌های قدیمی
    for post in Post.objects.all():
        # مثال: اگر title خالی بود، از content استفاده کنید
        if not post.title:
            post.title = post.content[:50] + "..."
            post.save()
        
        # مثال: محاسبه slug از title
        if not hasattr(post, 'slug') or not post.slug:
            from django.utils.text import slugify
            post.slug = slugify(post.title)
            post.save()

def reverse_migration(apps, schema_editor):
    # برای برگشت migration (اختیاری)
    pass

class Migration(migrations.Migration):
    dependencies = [
        ('blog', '0001_initial'),
    ]
    
    operations = [
        # اضافه کردن فیلد slug
        migrations.AddField(
            model_name='post',
            name='slug',
            field=models.SlugField(blank=True, null=True),
        ),
        # اجرای کد پایتون برای migrate داده‌ها
        migrations.RunPython(migrate_old_data, reverse_migration),
        # حالا که داده‌ها migrate شدن، می‌تونیم unique=True کنیم
        migrations.AlterField(
            model_name='post',
            name='slug',
            field=models.SlugField(unique=True),
        ),
    ]

آماده رفتن به درس بعدی هستید؟

این درس را به پایان رساندید و می‌توانید به درس بعدی بروید.