2016-03-14 23 views
5

CharField - ForeignKey arasındaki Django modellerimden birinde bir alanın türünü değiştirmem gerekiyor. Alanlar zaten veri ile doldurulmuş, bu yüzden bunu yapmak için en iyi ya da doğru yolun ne olduğunu merak ediyordum. Alan türünü güncelleyebilir ve geçiş yapabilir miyim ya da farkında olmak için herhangi bir 'gotchas' var mı? N.B: Sadece vanilya Django yönetim işlemlerini kullanıyorum (makemigrations ve migrate), Güney değil.CharField - ForeignKey için Django model alanının türünü değiştir

+2

CharField üzerinde benzersiz bir kısıtlama yoksa, yinelenen değerlere dikkat edin? Daha önce verileri kopyalayıp çoğaltmadığınıza veya sadece kendi masasına taşınmaya mı bağlı olduğuna bağlı. İkincisi, yapılacak en iyi şey, verilerinizin ne olduğuna bağlı olarak değişir. Django, CharField ve ForeignKey arasında bir tür sihirli dönüşüm yapamaz. Kendinizi duyarlı bir göçü yazmanız gerekecek. – user234461

+1

Bence bu aradığın şeye benziyor. http://stackoverflow.com/questions/5373906/changing-the-django-data-type-in-models-without-droping-the-table – Vibhu

cevap

25

Bu, çok aşamalı geçiş yapmak istediğiniz bir durumdur. Bunun için önerim, aşağıdaki gibi bir şey olurdu.

Öncelikle, bir uygulama discography denilen iç kıyafetleri, bu başlangıçtaki modeldir varsayalım:

from django.db import models 

class Album(models.Model): 
    name = models.CharField(max_length=255) 
    artist = models.CharField(max_length=255) 

Şimdi, bunun yerine sanatçı için bir ForeignKey kullanmak istediğinizi biliyoruz. Bahsedildiği gibi, bu sadece basit bir süreç değil. Birkaç adımda yapılmalıdır.

from django.db import models 

class Album(models.Model): 
    name = models.CharField(max_length=255) 
    artist = models.CharField(max_length=255) 
    artist_link = models.ForeignKey('Artist', null=True) 

class Artist(models.Model): 
    name = models.CharField(max_length=255) 

... ve bu değişim için bir göç oluşturun:

Adım 1, boş olarak işaretlemek emin olarak, ForeignKey için yeni bir alan ekleyin.

./manage.py makemigrations discography 

2. adım, yeni alanınızı doldurun. Bunu yapmak için boş bir göç oluşturmanız gerekir. Eğer bu boş göç sahip olduktan sonra

./manage.py makemigrations --empty --name transfer_artists discography 

, kendi kayıtlarını birbirine bağlamak için kendisine tek RunPython operasyonu eklemek istiyorum. Bu durumda, böyle bir şey olabilir:

def link_artists(apps, schema_editor): 
    Album = apps.get_model('discography', 'Album') 
    Artist = apps.get_model('discography', 'Artist') 
    for album in Album.objects.all(): 
     artist, created = Artist.objects.get_or_create(name=album.artist) 
     album.artist_link = artist 
     album.save() 

Artık veri yeni bir alana aktarılmasını, aslında yapılabilir ve olduğu gibi her şey için yeni alanını kullanarak, her şeyi bırakın. Ya da, biraz temizlik yapmak isterseniz, iki tane daha geçişi daha oluşturmak istersiniz.

İlk geçişiniz için, orijinal alanınızı silmek isteyeceksiniz, artist. İkinci geçişiniz için artist_link numaralı yeni alanı artist olarak yeniden adlandırın.

Bu, Django'nun işlemleri doğru şekilde tanımasını sağlamak için birden çok adımda gerçekleştirilir. Bunu işlemek için el ile bir geçiş oluşturabilirsiniz, ancak bunu anlamanız için size bırakacağım.

+0

Sorunuz ve kapsamlı yanıtınız için teşekkür ederiz. Bu da beni son olarak Django göçlerini öğrenmek ve doğru bir şekilde öğrenmek için beni uyardı! – ChrisM

+0

Ancak, ./manage.py makemigrations --empty ... 'olmalı? 2. adımda 'makemigration' (tekil) var. – ChrisM

+0

Ah, evet, yazım hatası yakaladığınız için teşekkürler! –