انتقال پایگاه داده

اکنون که می‌خواهیم پایگاه داده را منتقل کنیم، جانگو آن را تغییر می‌دهد تا بتواند بین هر موضوع و یک کاربر ارتباطی برقرار کند. برای انجام انتقال جانگو باید بداند موضوعاتی را که قبلاً ایجاد شده‌اند به کدام کاربر ربط دهد. ساده‌ترین رویکرد این است که برای شروع تمام موضوع‌های موجود را به یک کاربر نسبت دهیم—مثلاً ابرکاربر. امّا ابتدا باید شماره‌ی آن کاربر را بدانیم.

بیایید به شماره‌ی تمام کاربرانی که تا الان ساخته‌ایم نگاهی بیندازیم. یک نشست پوسته‌ی جانگو اجرا کنید و دستورهای زیر را وارد کنید:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
(ll_env)learning_log$ python manage.py shell

>>> from django.contrib.auth.models import User

>>> User.objects.all()

<QuerySet [<User: ll_admin>, <User: eric>, <User: willie>]>

>>> for user in User.objects.all():
...     print(user.username, user.id)
...

ll_admin 1
eric 2
willie 3

>>>

در ۱ مدل User را داخل نشست پوسته وارد می‌کنیم. سپس به تمام کاربرانی که تا کنون ساخته‌ایم نگاهی می‌اندازیم (۲). خروجی سه کاربر را نشان می‌دهد: ll_admin، eric و willie.

در ۳ در لیست کاربران حلقه می‌زنیم و نام کاربری و شماره‌ی هر کاربر را چاپ می‌کنیم. زمانی که جانگو درباره‌ی کاربری سوال می‌کند که قرار است تمام موضوع‌های موجود به او نسبت یابد، یکی از این سه شماره را وارد می‌کنیم.

انتقال پایگاه داده

حال که شماره‌ی کاربران را می‌دانیم می‌توانیم پایگاه داده را انتقال دهیم. زمانی که می‌خواهیم این کار را انجام دهیم پایتون دو گزینه پیش روی ما می‌گذارد: یا مدل Topic را موقّتاً به یکی از کاربران نسبت دهیم یا خودمان در فایل models.py یک حالت پیش‌فرض تعیین کنیم تا پایتون بر اساس آن عمل کند. گزینه‌ی ۱ را انتخاب کنید:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(ll_env)learning_log$ python manage.py makemigrations learning_logs

You are trying to add a non-nullable field 'owner' to topic without a default;
we can't do that (the database needs something to populate existing rows).

Please select a fix:

1) Provide a one-off default now (will be set on all existing rows with a
   null value for this column)

2) Quit, and let me add a default in models.py

Select an option: 1

Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do
e.g. timezone.now

Type 'exit' to exit this prompt

>>> 1

Migrations for 'learning_logs':
  learning_logs/migrations/0003_topic_owner.py
- Add field owner to topic

(ll_env)learning_log$

کار را با صدور فرمان makemigrations در ۱ آغاز می‌کنیم. در خروجی ۲، جانگو اعلام می‌کند که در حال افزودن یک فیلد اجباری (non-nullable) به مدل موجود (topic) هستیم و هیچ مقدار پیش‌فرضی تعیین نشده است. جانگو به ما دو گزینه می‌دهد (۳): می‌توانیم همین الان یک مقدار پیش‌فرض اعلام کنیم یا خارج شویم و مقدار پیش‌فرضی در models.py تعیین کنیم. در ۴ گزینه‌ی یکم را انتخاب کرده‌ایم. جانگو سپس مقدار پیش‌فرض را از ما می‌پرسد (۵).

برای ربط دادن به کاربر مدیر اوّلیّه، ll_admin، شماره‌ی کاربر ۱ را وارد کردم (۶). می‌توانید شماره‌ی هر کاربری را وارد کنید؛ حتماً نباید ابرکاربر باشد. سپس جانگو به کمک این مقدار پایگاه داده را منتقل کرده و فایل 0003_topic_owner.py را می‌سازد که فیلد owner را به مدل Topic اضافه می‌کند.

حال می‌توانیم عملیّات انتقال را اجرایی کنیم. این دستورها را در یک محیط مجازی فعّال وارد کنید:

1
2
3
4
5
6
7
8
9
(ll_env)learning_log$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, learning_logs, sessions

Running migrations:
  Applying learning_logs.0003_topic_owner... OK

(ll_env)learning_log$

جانگو انتقال جدید را اعمال می‌کند و نتیجه OK است (۱).

می‌توانیم در یک نشست پوسته بررسی کنیم که آیا انتقال مطابق انتظار ما انجام شده یا نه:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
>>> from learning_logs.models import Topic

>>> for topic in Topic.objects.all():
...           print(topic, topic.owner)
...

Chess ll_admin
Rock Climbing ll_admin

>>>

Topic را از learning_logs.models وارد می‌کنیم و سپس در تمام موضوعات موجود حلقه می‌زنیم تا هر موضوع و کاربر صاحب آن را چاپ کنیم (۲). می‌توانید ببینید که اکنون تمام موضوعات به کاربر ll_admin تعلّق دارند. (اگر هنگام اجرای این کد به مشکل خوردید یک بار پوسته را ببندید و دوباره باز کنید.)

نکته
شما می‌توانید به جای جابه‌جایی پایگاه داده، به سادگی آن را بازنشانی کنید امّا تمام اطّلاعات موجود در آن را از دست خواهید داد. آموختن نحوه‌ی جابه‌جایی یک پایگاه‌داده با حفظ یکپارچگی داده‌های کاربران تمرین خوبی است. اگر می‌خواهید یک پایگاه داده‌ی تازه راه بیندازید فرمان python manage.py flush را برای بازسازی ساختار پایگاه داده صادر کنید. شما باید یک ابرکاربر جدید بسازید و تمام داده‌هایتان از دست خواهد رفت.