[Django] Migration đào sâu- Part 1

taiphuong
4 min readJun 2, 2019

Ở phần trước bạn đã tìm hiểu về migration cơ bản. Bây giờ hãy xem migration có gì hay?

[Django] Migration đào sâu

How Migrations Know What to Migrate

Các mà migrations biết cái nào cần migrate. Bạn còn lưu dự án trước chứ nhỉ. Từ app bitcoin_tracker chạy migrate lần nữa, Cái gì sẽ xảy ra tiếp theo. Chẳng có gì cả. Chính xác là vậy.

Bởi vì mặc định Django không bao giờ chạy lại migration nhiều hơn 1 lần trên cùng 1 db.Nó được quản lý bởi 1 bảng gọi là django_migrations, nó được tạo ra trên db của bạn trong lần đầu tiên gọi nó. Trên mỗi lần migrations được gọi hay fake là một dòng mới được tạo trên bảng này.

Ví dụ:

Không thú vị lắm vì đây chỉ là 1 lần migration, nhưng sẽ có những dòng mới được thêm vào sau đó.

Ở lần chạy migration tiếp theo, nó sẽ bỏ qua những migration file được liệt kê ở bảng này. Có nghĩa là thậm chí nếu bạn thay đổi bằng tay trên file đó, nó cũng bỏ qua luôn.

The Migration File

Những file bạn tạo ra sao khi chạy lệnh ./manage.py makemigrations <appname>

Migrations của Django tạo ra những file này, nó mô tả cách tạo các bảng thích hợp trên db. Tất cả những file này đều chứa trong folder migration.

Xem một ví dụ về migration file trong dự án này.

# File: historical_data/migrations/0001_initial.pyfrom django.db import models, migrationsclass Migration(migrations.Migration):
dependencies = []
operations = [
migrations.CreateModel(
name='PriceHistory',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, primary_key=True, auto_created=True)),
('date', models.DateTimeField(auto_now_add=True)),
('price', models.DecimalField(decimal_places=2, max_digits=5)),
('volume', models.PositiveIntegerField()),
('total_btc', models.PositiveIntegerField()),
],
options={
},
bases=(models.Model,),
),
]

Bạn có thể thấy class Migration() được kế thừa django.db.migrations. Class này chưa 2 list quan trọng là dependencies, operations. Bạn sẽ được tìm hiểu bên dưới.

Migration dependencies

Đây là một danh sách những migration nào bị buộc sẽ chạy trước, trước khi migration này chạy.

Trong trường hợp trên thì không có dependencies cần phải chạy trước. Nhưng nếu bạn có bất kỳ quan hệ là khóa ngoại nào, ví dụ, khi bạn sẽ phải chắc chắn rằng model được tạo trước khi thêm khoá ngoại vào đó. Vì vậy hãy giả sử rằng bạn có một app khác gọi là main, nó định nghĩa các bảng có khoá ngoại để tham chiếu tới, hãy làm như sau:

dependencies = [
('main', '__first__'),
]
# hoặc có thể dùng tên file như sau:
dependencies = [
('main', '0001_initial'),
]

Phần dependencies có thể được kết hợp với nhiều dependencies khác nhau. Chức năng này khá linh hoạt, vì bạn có thể xử lý hợp lý mặc dù các khoá ngoại ở các app khác nhau. Nó cũng có ý nghĩa rằng việc đánh số từ 0001, 0002, 0003 không quan trọng vì bạn có thể thay đổi việc chạy trước sau bằng dependencies.

Migration operations

  • CreateModel.
  • DeleteModel.
  • RenameModel
  • AlterModelTable
  • AlterUniqueTogether
  • AlteIndexTogether.
  • AddField
  • RemoveField
  • RenameField
  • RunSQL
  • RunPython

Về thực tế là bạn có thể tự viết được phần migration. Nhìn chung khi bạn chạy makemigrations, Django sẽ tạo những file cần thiết với dependencies và operations thích hợp mà bạn cần. Tuy nhiên, hãy hiểu cách hoạt động của nó để làm cho cuộc sống của bạn dễ dàng hơn :).

Example

Giờ bạn cần làm một số thay đổi trên model để thấy sự kiểm tra sự thay đổi trên migrations.

class PriceHistory(models.Model):
date = models.DateTimeField(auto_now_add=True)
# Bitcoin to the moon (we need more digits)
price = models.DecimalField(max_digits=8, decimal_places=2)
volume = models.PositiveIntegerField()
total_btc = models.PositiveIntegerField()
market_cap = models.PositiveIntegerField(null=True)

Bị tăng giá Bitcoin chúng tôi phải có quyết định là chúng tôi cần 1 con số lớn hơn cho field price, và theo dõi luôn vốn hoá của thị trường bằng field market_cap. Run it

./manage.py makemigrations --name <some name>

Chúng ta sẽ có file dạng giống như vầy:

class Migration(migrations.Migration):

dependencies = [
('historical_data', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='PriceHistory',
name='market_cap',
field=models.PositiveIntegerField(null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='PriceHistory',
name='price',
field=models.DecimalField(max_digits=8, decimal_places=2),
),
]

Chú ý ở dependencies bạn thấy có 0001_initial và có 2 operations: AlterField và AddField.

Viewing the Migration

Thậm chí bạn không cần phải lo lắng về cách mà SQL làm migrations này. Nếu như hiếu kì bạn có thể run bằng câu lệnh này:

$ ./manage.py sqlmigration <app-name> <migration-name>

Như vậy chúng ta kết thúc phần Migration đào sâu ở đây.

Hẹn gặp lại các bạn ở bài kế tiếp.

--

--