Django - Làm cách nào để đổi tên trường mẫu bằng cách sử dụng Nam?


209

Tôi muốn thay đổi tên của các trường cụ thể trong mô hình:

class Foo(models.Model):
    name = models.CharField()
    rel  = models.ForeignKey(Bar)

nên đổi thành:

class Foo(models.Model):
    full_name     = models.CharField()
    odd_relation  = models.ForeignKey(Bar)

Cách dễ nhất để làm điều này bằng cách sử dụng Nam là gì?


7
Xem thêm stackoverflow.com/questions/2862979/ để đổi tên mô hình thay vì trường mô hình .
Ốc cơ khí

Câu trả lời:


230

Bạn có thể sử dụng db.rename_columnchức năng.

class Migration:

    def forwards(self, orm):
        # Rename 'name' field to 'full_name'
        db.rename_column('app_foo', 'name', 'full_name')




    def backwards(self, orm):
        # Rename 'full_name' field to 'name'
        db.rename_column('app_foo', 'full_name', 'name')

Đối số đầu tiên db.rename_columnlà tên bảng, vì vậy điều quan trọng cần nhớ là Django tạo tên bảng như thế nào :

Django tự động lấy tên của bảng cơ sở dữ liệu từ tên của lớp mô hình của bạn và ứng dụng có chứa nó. Tên bảng cơ sở dữ liệu của một mô hình được xây dựng bằng cách nối "nhãn ứng dụng" của mô hình - tên bạn đã sử dụng trong quản lý startapp - với tên lớp của mô hình, với dấu gạch dưới giữa chúng.

Trong trường hợp bạn có một tên mô hình nhiều từ, vỏ lạc đà, chẳng hạn như ProjectItem, tên bảng sẽ là app_projectitem(nghĩa là một dấu gạch dưới sẽ không được chèn vào giữa projectitemmặc dù chúng có vỏ lạc đà).


2
Điều đó sẽ hoạt động trên tên \ full_name, nhưng không phải trên trường quan hệ, phải không?
Jonathan

23
LƯU Ý QUAN TRỌNG: nếu bạn sẽ sử dụng cái này, hãy đảm bảo "app_foo" là tên bảng cơ sở dữ liệu, ví dụ: "mainapp_profile", "name" là tên cột cũ của cơ sở dữ liệu (không phải tên trường mô hình), ví dụ: "user_id" và "full_name" sẽ là tên mới mà bạn muốn cột có (một lần nữa, cột cơ sở dữ liệu và không phải tên trường). Vì vậy: db.rename_column ('mainapp_profile', 'user_id', 'new_user_id') Ngoài ra, nếu bạn đang xử lý các khóa ngoại, bạn nên có phần "_id" trong chúng khi đổi tên.
Gezim

3
Nếu bạn thực hiện thủ công db.rename_column này, bạn có thể phải thực hiện một sơ đồ giả sau đó để dọn dẹp mọi thứ sao lưu. Đó là lần đầu tiên di chuyển thay đổi với việc đổi tên các cột. Sau đó sửa mô hình (để có tên cập nhật), sau đó thực hiện ./manage.py ứng dụng schemamigration --auto && ./manage.py di chuyển ứng dụng --fake).
dr jimbob

24
Bạn cũng có thể sử dụng ./manage.py schemamigration my_app renaming_column_x --empty để tạo một di chuyển trống và chỉ để đặt mã vào đó
Ilian Iliev

11
--empty không giúp được gì nhiều, thay vào đó hãy sử dụng --auto và sửa đổi di chuyển đã tạo. Bằng cách này, trường sẽ không yêu cầu đã bị xóa cho lần di chuyển tiếp theo của mô hình.
yasc

39

Đây là những gì tôi làm:

  1. Làm cho tên cột thay đổi trong mô hình của bạn (trong ví dụ này là như vậy myapp/models.py)
  2. Chạy ./manage.py schemamigration myapp renaming_column_x --auto

Lưu ý renaming_column_xcó thể là bất cứ điều gì bạn thích, đó chỉ là một cách để đặt tên mô tả cho tệp di chuyển.

Điều này sẽ tạo cho bạn một tệp có tên myapp/migrations/000x_renaming_column_x.pysẽ xóa cột cũ của bạn và thêm một cột mới.

Sửa đổi mã trong tệp này để thay đổi hành vi di chuyển thành đổi tên đơn giản:

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Renaming column 'mymodel.old_column_name' to 'mymodel.new_column_name'
        db.rename_column(u'myapp_mymodel', 'old_column_name', 'new_column_name')

    def backwards(self, orm):
        # Renaming column 'mymodel.new_column_name' to 'mymodel.old_column_name'
        db.rename_column(u'myapp_mymodel', 'new_column_name', 'old_column_name')

tên của cột trong lệnh của bạn là gì? xhay column_x?
andilabs

Một phần của lệnh bạn đang đề cập chỉ được sử dụng để đặt tên cho việc di chuyển, nó có thể là bất cứ điều gì bạn thích. Tên cột sẽ cần được chỉ định trong tệp di chuyển khi bạn chỉnh sửa nó.
donturner

2
Tạo --autodi chuyển đầu tiên là một mẹo tuyệt vời. Nó tránh các vấn đề với Tủ đông ORM phía Nam, xảy ra nếu việc di chuyển chỉ có forwardsbackwardsphương thức, nhưng không chứa modelđối tượng bị đóng băng .
mwcz

Làm cách nào để tôi trả lời câu hỏi phía nam 'Vì bạn đang xóa trường này, bạn PHẢI chỉ định mặc định'?
Bryce

3
Một vấn đề tôi gặp phải với phương pháp này là db.rename_columnkhông đổi tên các ràng buộc liên quan đến cột. Việc di chuyển sẽ vẫn hoạt động nhưng bạn sẽ có các ràng buộc được đặt tên theo tên cột cũ. Tôi đã có một cột với một ràng buộc duy nhất, đổi tên nó bằng phương thức này, đã kiểm tra rằng ràng buộc duy nhất vẫn tồn tại và có lỗi nhưng tên của ràng buộc đó vẫn sử dụng tên cột cũ. Có lẽ một điều rõ ràng db.delete_uniquedb.create_uniquesẽ làm điều đó nhưng tôi quyết định đi theo giải pháp của sjh.
Louis

15

Tôi không biết về cột db.rename, nghe có vẻ tiện dụng, tuy nhiên trước đây tôi đã thêm cột mới dưới dạng một lược đồ, sau đó tạo một cơ sở dữ liệu để di chuyển các giá trị vào trường mới, sau đó là một lược đồ thứ hai để loại bỏ cột cũ


Tôi cũng vậy. Vấn đề với kỹ thuật lược đồ-dữ liệu-lược đồ là bạn kết thúc với các tên khác nhau cho các trường / mô hình của bạn. Đôi khi đây là một vấn đề nếu bạn sử dụng tên chính tắc để cho phép người điều phối ...
Jonathan

Tôi mới thử cái này và nó không hoạt động vì có xung đột tên. Tôi đã có cùng một FK nhưng tên khác nhau. Nó không xác nhận. Vì vậy, đừng làm điều này.
Gezim

2
@jonathan, anh ấy muốn các tên khác nhau! ... @pilgrim, quan tâm để gửi một số mã? Tôi đã thực hiện điều này nhiều lần trong tuần này, nếu các mô hình của bạn không xác thực thì phía nam sẽ không tạo ra sự di chuyển.
sjh

Điều đó sẽ hoạt động, nhưng có lẽ sẽ chậm hơn 'rename_column' mà người khác đã đề xuất. Tôi biết MySQL có thể thực hiện "cột thay đổi ... đổi tên" (hoặc bất cứ thứ gì) khá nhanh chóng.
Rory

1
@Rory db.rename_columnsẽ không đổi tên các ràng buộc cho bạn để bạn phải xử lý thủ công. Nếu bạn quên làm điều đó, quá trình di chuyển sẽ hoạt động ngoại trừ việc bạn không biết đến bạn có thể có một ràng buộc vẫn sử dụng tên cột cũ. Tôi không rõ liệu vấn đề này chỉ là do mỹ phẩm hay là trong một cuộc di cư trong tương lai nơi mà sự ràng buộc nên được thao túng hoặc bỏ đi, Nam sẽ không thể tìm thấy nó. Ở bất cứ giá nào, thực hiện nó ở đây như sjh gợi ý là cách an toàn để làm điều đó: bạn có thể để Nam tìm ra những gì nó nên được tìm ra.
Louis

10

Django 1.7 đã giới thiệu Di chuyển, vì vậy bây giờ bạn thậm chí không cần phải cài đặt gói bổ sung để quản lý việc di chuyển của mình.

Để đổi tên mô hình của bạn, trước tiên bạn cần tạo di chuyển trống:

$ manage.py makemigrations <app_name> --empty

Sau đó, bạn cần chỉnh sửa mã di chuyển của mình như thế này:

from django.db import models, migrations

class Migration(migrations.Migration):

dependencies = [
    ('yourapp', 'XXXX_your_previous_migration'),
]

operations = [
    migrations.RenameField(
        model_name='Foo',
        old_name='name',
        new_name='full_name'
    ),
    migrations.RenameField(
        model_name='Foo',
        old_name='rel',
        new_name='odd_relation'
    ),
]

Và sau đó bạn cần chạy:

$ manage.py migrate <app_name>

5

Chỉ cần thay đổi mô hình và chạy makemigrationstrong 1.9

Django tự động phát hiện ra rằng bạn đã xóa và tạo một trường duy nhất và hỏi:

Did you rename model.old to model.new (a IntegerField)? [y/N]

Nói có, và di chuyển đúng được tạo ra. Ma thuật.


0
  1. Thêm vào southứng dụng đã cài đặt của bạn trong tệp cài đặt dự án.
  2. Nhận xét trường / bảng đã thêm / sửa đổi.
  3. $ manage.py Schemamigration <app_name> --initial
  4. $ manage.py migrate <app_name> --Fake
  5. Bỏ bình luận trường và viết cái đã sửa đổi
  6. $ manage.py Schemamigration --auto
  7. $ manage.py migrate <app_name>

Nếu bạn đang sử dụng 'pycharm', thì bạn có thể sử dụng 'ctrl + shift + r' thay vì 'Manage.py' và 'shift' cho các tham số.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.