Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Đào sâu hơn vào các cuộc di cư Django

Đây là bài viết thứ hai trong loạt bài về di cư Django của chúng tôi:

  • Phần 1:Django Migrations:A Primer
  • Phần 2:Tìm hiểu sâu hơn về các cuộc di cư Django (bài viết hiện tại)
  • Phần 3:Di chuyển dữ liệu
  • Video:Django 1.7 Migrations - A Primer

Trong phần trước của loạt bài này, bạn đã biết về mục đích của việc di chuyển Django. Bạn đã làm quen với các mẫu sử dụng cơ bản như tạo và áp dụng di chuyển. Bây giờ đã đến lúc tìm hiểu sâu hơn về hệ thống di chuyển và xem xét một số cơ chế cơ bản của nó.

Đến cuối bài viết này, bạn sẽ biết:

  • Cách Django theo dõi quá trình di cư
  • Cách di chuyển biết hoạt động cơ sở dữ liệu nào cần thực hiện
  • Cách xác định sự phụ thuộc giữa các lần di chuyển

Sau khi hoàn thành phần này của hệ thống di chuyển Django, bạn sẽ chuẩn bị tốt để tạo các di chuyển tùy chỉnh của riêng mình. Hãy bắt đầu ngay nơi chúng ta đã dừng lại!

Bài viết này sử dụng bitcoin_tracker Dự án Django được xây dựng trong Django Migrations:A Primer. Bạn có thể tạo lại dự án đó bằng cách làm qua bài viết đó hoặc bạn có thể tải xuống mã nguồn:

Tải xuống mã nguồn: Nhấp vào đây để tải xuống mã cho dự án di chuyển Django mà bạn sẽ sử dụng trong bài viết này.


Làm thế nào Django biết nên áp dụng phương thức di chuyển nào

Hãy tóm tắt lại bước cuối cùng của bài viết trước trong loạt bài này. Bạn đã tạo một lần di chuyển và sau đó áp dụng tất cả các lần di chuyển có sẵn với python manage.py migrate .Nếu lệnh đó chạy thành công, thì các bảng cơ sở dữ liệu của bạn bây giờ khớp với định nghĩa của mô hình của bạn.

Điều gì xảy ra nếu bạn chạy lại lệnh đó? Hãy dùng thử:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, historical_data, sessions
Running migrations:
  No migrations to apply.

Không có chuyện gì xảy ra! Khi quá trình di chuyển đã được áp dụng cho cơ sở dữ liệu, Django sẽ không áp dụng lần di chuyển này cho cơ sở dữ liệu cụ thể đó nữa. Đảm bảo rằng quá trình di chuyển chỉ được áp dụng một lần yêu cầu phải theo dõi các quá trình di chuyển đã được áp dụng.

Django sử dụng bảng cơ sở dữ liệu có tên django_migrations . Django tự động tạo bảng này trong cơ sở dữ liệu của bạn vào lần đầu tiên bạn áp dụng bất kỳ di chuyển nào. Đối với mỗi lần di chuyển được áp dụng hoặc giả mạo, một hàng mới sẽ được chèn vào bảng.

Ví dụ:đây là bảng này trông như thế nào trong bitcoin_tracker của chúng tôi dự án:

ID Ứng dụng Tên Đã áp dụng
1 contenttypes 0001_initial 2019-02-05 20:23:21.461496
2 auth 0001_initial 2019-02-05 20:23:21.489948
3 admin 0001_initial 2019-02-05 20:23:21.508742
4 admin 0002_logentry_remove... 2019-02-05 20:23:21.531390
5 admin 0003_logentry_add_ac... 2019-02-05 20:23:21.564834
6 contenttypes 0002_remove_content_... 2019-02-05 20:23:21.597186
7 auth 0002_alter_permissio... 2019-02-05 20:23:21.608705
8 auth 0003_alter_user_emai... 2019-02-05 20:23:21.628441
9 auth 0004_alter_user_user... 2019-02-05 20:23:21.646824
10 auth 0005_alter_user_last... 2019-02-05 20:23:21.661182
11 auth 0006_require_content... 2019-02-05 20:23:21.663664
12 auth 0007_alter_validator... 2019-02-05 20:23:21.679482
13 auth 0008_alter_user_user... 2019-02-05 20:23:21.699201
14 auth 0009_alter_user_last... 2019-02-05 20:23:21.718652
15 historical_data 0001_initial 2019-02-05 20:23:21.726000
16 sessions 0001_initial 2019-02-05 20:23:21.734611
19 historical_data 0002_switch_to_decimals 2019-02-05 20:30:11.337894

Như bạn có thể thấy, có một mục nhập cho mỗi lần di chuyển được áp dụng. Bảng không chỉ chứa các di chuyển từ historical_data của chúng tôi ứng dụng, mà còn là di chuyển từ tất cả các ứng dụng đã cài đặt khác.

Trong lần di chuyển tiếp theo được chạy, Django sẽ bỏ qua các di chuyển được liệt kê trong bảng cơ sở dữ liệu. Điều này có nghĩa là, ngay cả khi bạn thay đổi thủ công tệp của quá trình di chuyển đã được áp dụng, Django sẽ bỏ qua những thay đổi này, miễn là đã có mục nhập cho nó trong cơ sở dữ liệu.

Bạn có thể lừa Django chạy lại quá trình di chuyển bằng cách xóa hàng tương ứng khỏi bảng, nhưng điều này hiếm khi là một ý tưởng hay và có thể khiến bạn bị hỏng hệ thống di chuyển.



Tệp di chuyển

Điều gì sẽ xảy ra khi bạn chạy python manage.py makemigrations <appname> ? Django tìm kiếm các thay đổi được thực hiện đối với các mô hình trong ứng dụng của bạn <appname> . Nếu nó tìm thấy bất kỳ, chẳng hạn như một mô hình đã được thêm vào, thì nó sẽ tạo một tệp di chuyển trong migrations thư mục con. Tệp di chuyển này chứa danh sách các thao tác để đồng bộ hóa lược đồ cơ sở dữ liệu với định nghĩa mô hình của bạn.

Lưu ý: Ứng dụng của bạn phải được liệt kê trong INSTALLED_APPS và nó phải chứa migrations thư mục có __init__.py tập tin. Nếu không, Django sẽ không tạo bất kỳ quá trình di chuyển nào cho nó.

migrations thư mục được tạo tự động khi bạn tạo ứng dụng mới với startapp lệnh quản lý, nhưng rất dễ quên khi tạo ứng dụng theo cách thủ công.

Các tệp di chuyển chỉ là Python, vì vậy hãy xem tệp di chuyển đầu tiên trong historical_prices ứng dụng. Bạn có thể tìm thấy nó tại historical_prices/migrations/0001_initial.py . Nó sẽ trông giống như sau:

from django.db import models, migrations

class 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,),
        ),
    ]

Như bạn có thể thấy, nó chứa một lớp duy nhất được gọi là Migration kế thừa từ django.db.migrations.Migration . Đây là lớp mà khung di chuyển sẽ tìm kiếm và thực thi khi bạn yêu cầu nó áp dụng di chuyển.

Migration lớp chứa hai danh sách chính:

  1. dependencies
  2. operations

Hoạt động di chuyển

Hãy xem xét các operations liệt kê đầu tiên. Bảng này chứa các thao tác sẽ được thực hiện như một phần của quá trình di chuyển. Các phép toán là lớp con của lớp django.db.migrations.operations.base.Operation . Dưới đây là các hoạt động phổ biến được tích hợp vào Django:

Lớp hoạt động Mô tả
CreateModel Tạo một mô hình mới và bảng cơ sở dữ liệu tương ứng
DeleteModel Xóa một mô hình và xóa bảng cơ sở dữ liệu của nó
RenameModel Đổi tên mô hình và đổi tên bảng cơ sở dữ liệu của nó
AlterModelTable Đổi tên bảng cơ sở dữ liệu cho một mô hình
AlterUniqueTogether Thay đổi các ràng buộc duy nhất của một mô hình
AlterIndexTogether Thay đổi chỉ mục của một mô hình
AlterOrderWithRespectTo Tạo hoặc xóa _order cột cho một mô hình
AlterModelOptions Thay đổi các tùy chọn mô hình khác nhau mà không ảnh hưởng đến cơ sở dữ liệu
AlterModelManagers Thay đổi các trình quản lý có sẵn trong quá trình di chuyển
AddField Thêm một trường vào một mô hình và cột tương ứng trong cơ sở dữ liệu
RemoveField Xóa một trường khỏi mô hình và xóa cột tương ứng khỏi cơ sở dữ liệu
AlterField Thay đổi định nghĩa của trường và thay đổi cột cơ sở dữ liệu của trường đó nếu cần
RenameField Đổi tên trường và nếu cần, cả cột cơ sở dữ liệu của trường đó
AddIndex Tạo chỉ mục trong bảng cơ sở dữ liệu cho mô hình
RemoveIndex Xóa chỉ mục khỏi bảng cơ sở dữ liệu cho mô hình

Lưu ý cách các hoạt động được đặt tên sau các thay đổi được thực hiện đối với định nghĩa mô hình, không phải các hành động được thực hiện trên cơ sở dữ liệu. Khi bạn áp dụng một quá trình di chuyển, mỗi thao tác có trách nhiệm tạo ra các câu lệnh SQL cần thiết cho cơ sở dữ liệu cụ thể của bạn. Ví dụ:CreateModel sẽ tạo CREATE TABLE Câu lệnh SQL.

Ngoài ra, di chuyển có hỗ trợ cho tất cả các cơ sở dữ liệu tiêu chuẩn mà Django hỗ trợ. Vì vậy, nếu bạn tuân theo các thao tác được liệt kê ở đây, thì bạn có thể thực hiện nhiều hơn hoặc ít hơn bất kỳ thay đổi nào đối với mô hình của mình mà bạn muốn mà không cần phải lo lắng về SQL cơ bản. Đó là tất cả những gì đã làm cho bạn.

Lưu ý: Trong một số trường hợp, Django có thể không phát hiện chính xác các thay đổi của bạn. Nếu bạn đổi tên một mô hình và thay đổi một số trường của nó, thì Django có thể nhầm điều này với một mô hình mới.

Thay vì RenameModel và một số AlterField hoạt động, nó sẽ tạo ra một DeleteModel và một CreateModel hoạt động. Thay vì đổi tên bảng cơ sở dữ liệu cho mô hình, nó sẽ loại bỏ nó và tạo một bảng mới với tên mới, xóa tất cả dữ liệu của bạn một cách hiệu quả!

Hãy tạo thói quen kiểm tra các lần di chuyển đã tạo và kiểm tra chúng trên bản sao cơ sở dữ liệu của bạn trước khi chạy chúng trên dữ liệu sản xuất.

Django cung cấp thêm ba lớp hoạt động cho các trường hợp sử dụng nâng cao:

  1. RunSQL cho phép bạn chạy SQL tùy chỉnh trong cơ sở dữ liệu.
  2. RunPython cho phép bạn chạy bất kỳ mã Python nào.
  3. SeparateDatabaseAndState là một hoạt động chuyên biệt cho các mục đích sử dụng nâng cao.

Với các thao tác này, về cơ bản bạn có thể thực hiện bất kỳ thay đổi nào bạn muốn đối với cơ sở dữ liệu của mình. Tuy nhiên, bạn sẽ không tìm thấy các thao tác này trong quá trình di chuyển được tạo tự động với makemigrations lệnh quản lý.

Kể từ Django 2.0, cũng có một số hoạt động dành riêng cho PostgreSQL có sẵn trong django.contrib.postgres.operations mà bạn có thể sử dụng để cài đặt các phần mở rộng PostgreSQL khác nhau:

  • BtreeGinExtension
  • BtreeGistExtension
  • CITextExtension
  • CryptoExtension
  • HStoreExtension
  • TrigramExtension
  • UnaccentExtension

Lưu ý rằng quá trình di chuyển có chứa một trong các thao tác này yêu cầu người dùng cơ sở dữ liệu có đặc quyền siêu người dùng.

Cuối cùng nhưng không kém phần quan trọng, bạn cũng có thể tạo các lớp hoạt động của riêng mình. Nếu bạn muốn xem xét vấn đề đó, hãy xem tài liệu Django về cách tạo các hoạt động di chuyển tùy chỉnh.



Sự phụ thuộc khi di chuyển

Các phần phụ thuộc dependencies danh sách trong một lớp di chuyển chứa bất kỳ quá trình di chuyển nào phải được áp dụng trước khi có thể áp dụng quá trình di chuyển này.

Trong 0001_initial.py quá trình di chuyển mà bạn đã thấy ở trên, không có gì phải được áp dụng trước vì vậy không có phụ thuộc. Hãy xem lần di chuyển thứ hai trong historical_prices ứng dụng. Trong tệp 0002_switch_to_decimals.py , dependencies thuộc tính của Migration có một mục:

from django.db import migrations, models

class Migration(migrations.Migration):
    dependencies = [
        ('historical_data', '0001_initial'),
    ]
    operations = [
        migrations.AlterField(
            model_name='pricehistory',
            name='volume',
            field=models.DecimalField(decimal_places=3, max_digits=7),
        ),
    ]

Phần phụ thuộc ở trên cho biết rằng việc di chuyển 0001_initial của ứng dụng historical_data phải được chạy trước. Điều đó có ý nghĩa, bởi vì việc di chuyển 0001_initial tạo bảng chứa trường mà việc di chuyển 0002_switch_to_decimals muốn thay đổi.

Quá trình di chuyển cũng có thể phụ thuộc vào quá trình di chuyển từ một ứng dụng khác, như thế này:

class Migration(migrations.Migration):
    ...

    dependencies = [
        ('auth', '0009_alter_user_last_name_max_length'),
    ]

Điều này thường là cần thiết nếu một mô hình có Khóa ngoại trỏ đến một mô hình trong ứng dụng khác.

Ngoài ra, bạn cũng có thể thực thi quá trình di chuyển được chạy trước một lần di chuyển khác sử dụng thuộc tính run_before :

class Migration(migrations.Migration):
    ...

    run_before = [
        ('third_party_app', '0001_initial'),
    ]

Các phụ thuộc cũng có thể được kết hợp để bạn có thể có nhiều phụ thuộc. Chức năng này cung cấp rất nhiều tính linh hoạt, vì bạn có thể chứa các khóa ngoại phụ thuộc vào kiểu máy từ các ứng dụng khác nhau.

Tùy chọn xác định rõ ràng sự phụ thuộc giữa các lần di chuyển cũng có nghĩa là việc đánh số các lần di chuyển (thường là 0001 , 0002 , 0003 ,…) Không đại diện chính xác thứ tự áp dụng quá trình di chuyển. Bạn có thể thêm bất kỳ phần phụ thuộc nào bạn muốn và do đó kiểm soát thứ tự mà không cần phải đánh số lại tất cả các lần di chuyển.



Xem quá trình di chuyển

Bạn thường không phải lo lắng về SQL mà quá trình di chuyển tạo ra. Nhưng nếu bạn muốn kiểm tra kỹ xem SQL được tạo có hợp lý hay chỉ tò mò nó trông như thế nào, thì Django sẽ giúp bạn bao gồm sqlmigrate lệnh quản lý:

$ python manage.py sqlmigrate historical_data 0001
BEGIN;
--
-- Create model PriceHistory
--
CREATE TABLE "historical_data_pricehistory" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
    "date" datetime NOT NULL,
    "price" decimal NOT NULL,
    "volume" integer unsigned NOT NULL
);
COMMIT;

Làm điều đó sẽ liệt kê ra các truy vấn SQL cơ bản sẽ được tạo ra bởi quá trình di chuyển được chỉ định, dựa trên cơ sở dữ liệu trong settings.py của bạn tập tin. Khi bạn chuyển tham số --backwards , Django tạo SQL để hủy áp dụng việc di chuyển:

$ python manage.py sqlmigrate --backwards historical_data 0001
BEGIN;
--
-- Create model PriceHistory
--
DROP TABLE "historical_data_pricehistory";
COMMIT;

Khi bạn thấy đầu ra của sqlmigrate đối với quá trình di chuyển phức tạp hơn một chút, bạn có thể đánh giá cao rằng bạn không cần phải tạo tất cả SQL này bằng tay!




Cách Django phát hiện các thay đổi đối với mô hình của bạn

Bạn đã thấy tệp di chuyển trông như thế nào và danh sách Operation của nó như thế nào các lớp xác định các thay đổi được thực hiện đối với cơ sở dữ liệu. Nhưng làm cách nào Django biết chính xác những thao tác nào sẽ đi vào tệp di chuyển? Bạn có thể mong đợi rằng Django so sánh các mô hình của bạn với lược đồ cơ sở dữ liệu, nhưng không phải vậy.

Khi chạy makemigrations , Django không không kiểm tra cơ sở dữ liệu của bạn. Nó cũng không so sánh tệp mô hình của bạn với một phiên bản trước đó. Thay vào đó, Django thực hiện tất cả các lần di chuyển đã được áp dụng và xây dựng trạng thái dự án về các mô hình sẽ trông như thế nào. Trạng thái dự án này sau đó được so sánh với các định nghĩa mô hình hiện tại của bạn và danh sách các hoạt động được tạo, khi được áp dụng, sẽ cập nhật trạng thái dự án với các định nghĩa mô hình.


Chơi cờ với Django

Bạn có thể coi mô hình của mình giống như một bàn cờ vua, và Django là một đại kiện tướng cờ vua đang xem bạn thi đấu với chính mình. Nhưng kiện tướng không theo dõi từng bước di chuyển của bạn. Kiện tướng chỉ nhìn vào bảng khi bạn hô makemigrations .

Vì chỉ có một số nước đi hạn chế có thể xảy ra (và kiện tướng là đại kiện tướng), cô ấy có thể nghĩ ra các nước đi đã xảy ra kể từ lần cuối cùng cô ấy nhìn vào bảng. Cô ấy ghi chú một số và cho phép bạn chơi cho đến khi bạn hét lên makemigrations một lần nữa.

Khi nhìn vào bàn cờ lần sau, kiện tướng không nhớ bàn cờ trông như thế nào lần trước, nhưng bà có thể xem qua ghi chép của mình về các nước đi trước đó và xây dựng mô hình tinh thần về bàn cờ trông như thế nào.

Bây giờ, khi bạn hét migrate , kiện tướng sẽ chơi lại tất cả các nước đi đã ghi trên một bàn cờ vua khác và ghi chú vào một bảng tính mà các kỷ lục của cô ấy đã được áp dụng. Bàn cờ thứ hai này là cơ sở dữ liệu của bạn và bảng tính là django_migrations bảng.

Sự tương tự này khá phù hợp, bởi vì nó minh họa một cách độc đáo một số hành vi của việc di cư Django:

  • Di chuyển Django cố gắng hiệu quả: Giống như kiện tướng giả định rằng bạn thực hiện số lần di chuyển ít nhất, Django sẽ cố gắng tạo ra những lần di chuyển hiệu quả nhất. Nếu bạn thêm trường có tên A thành một mô hình, sau đó đổi tên nó thành B , rồi chạy makemigrations , sau đó Django sẽ tạo một quá trình di chuyển mới để thêm một trường có tên B .

  • Di chuyển Django có giới hạn của chúng: Nếu bạn thực hiện nhiều nước đi trước khi để kiện tướng nhìn vào bàn cờ, thì bà ta có thể không tập lại được động tác chính xác của từng quân cờ. Tương tự, Django có thể không đưa ra phương án di chuyển chính xác nếu bạn thực hiện quá nhiều thay đổi cùng một lúc.

  • Di chuyển Django mong muốn bạn chơi theo các quy tắc: Khi bạn làm bất cứ điều gì không mong muốn, chẳng hạn như lấy một quân cờ ngẫu nhiên ra khỏi bảng hoặc lộn xộn với các ghi chú, ban đầu, kiện tướng có thể không nhận thấy, nhưng sớm hay muộn, bà ấy sẽ bó tay và từ chối tiếp tục. Điều tương tự cũng xảy ra khi bạn sử dụng django_migrations bảng hoặc thay đổi lược đồ cơ sở dữ liệu của bạn bên ngoài di chuyển, chẳng hạn bằng cách xóa bảng cơ sở dữ liệu cho một mô hình.



Hiểu SeparateDatabaseAndState

Bây giờ bạn đã biết về trạng thái dự án mà Django xây dựng, đã đến lúc xem xét kỹ hơn hoạt động SeparateDatabaseAndState . Thao tác này có thể thực hiện chính xác những gì tên ngụ ý:nó có thể tách trạng thái dự án (mô hình tinh thần mà Django xây dựng) khỏi cơ sở dữ liệu của bạn.

SeparateDatabaseAndState được khởi tạo với hai danh sách hoạt động:

  1. state_operations chứa các hoạt động chỉ được áp dụng cho trạng thái dự án.
  2. database_operations chứa các hoạt động chỉ được áp dụng cho cơ sở dữ liệu.

Thao tác này cho phép bạn thực hiện bất kỳ loại thay đổi nào đối với cơ sở dữ liệu của mình, nhưng bạn có trách nhiệm đảm bảo rằng trạng thái dự án phù hợp với cơ sở dữ liệu sau đó. Các trường hợp sử dụng mẫu cho SeparateDatabaseAndState đang di chuyển một mô hình từ ứng dụng này sang ứng dụng khác hoặc tạo chỉ mục trên cơ sở dữ liệu khổng lồ mà không cần thời gian ngừng hoạt động.

SeparateDatabaseAndState là một hoạt động nâng cao và bạn sẽ không cần vào ngày đầu tiên làm việc với di chuyển và có thể không bao giờ. SeparateDatabaseAndState tương tự như phẫu thuật tim. Nó mang lại khá nhiều rủi ro và không phải là điều bạn làm chỉ để giải trí, nhưng đôi khi nó là một thủ tục cần thiết để giữ cho bệnh nhân sống sót.




Kết luận

Điều này kết thúc chuyến đi sâu của bạn vào cuộc di cư Django. Xin chúc mừng! Bạn đã đề cập đến khá nhiều chủ đề nâng cao và hiện đã có hiểu biết vững chắc về những gì xảy ra trong quá trình di cư.

Bạn đã học được rằng:

  • Django theo dõi các lần di chuyển đã áp dụng trong bảng di chuyển Django.
  • Di chuyển Django bao gồm các tệp Python thuần túy có chứa Migration lớp học.
  • Django biết những thay đổi nào cần thực hiện từ các thao tác dependencies danh sách trong Migration lớp học.
  • Django so sánh các mô hình của bạn với trạng thái dự án mà nó xây dựng từ quá trình di chuyển.

Với kiến ​​thức này, bây giờ bạn đã sẵn sàng giải quyết phần thứ ba của loạt bài về di chuyển Django, nơi bạn sẽ tìm hiểu cách sử dụng di chuyển dữ liệu để thực hiện các thay đổi một lần đối với dữ liệu của mình một cách an toàn. Hãy theo dõi!

Bài viết này đã sử dụng bitcoin_tracker Dự án Django được xây dựng trong Django Migrations:A Primer. Bạn có thể tạo lại dự án đó bằng cách làm qua bài viết đó hoặc bạn có thể tải xuống mã nguồn:

Tải xuống mã nguồn: Nhấp vào đây để tải xuống mã cho dự án di chuyển Django mà bạn sẽ sử dụng trong bài viết này.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bắt đầu Điều chỉnh Hiệu suất trong Cơ sở dữ liệu Azure SQL

  2. Lỗi, cạm bẫy và các phương pháp hay nhất của T-SQL - xoay và hủy chia

  3. Khám phá 10 khả năng ít được biết đến của Trình quản lý chẩn đoán SQL

  4. Giới thiệu về chốt

  5. ODBC nhanh đến mức nào? So sánh "Đã tải".