Django Changer un CharField en un ForeignKey


Exemple

Tout d'abord, supposons qu'il s'agisse de votre modèle initial, à l'intérieur d'une application appelée discography :

from django.db import models

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

Maintenant, vous vous rendez compte que vous voulez utiliser un ForeignKey pour l'artiste à la place. C'est un processus assez complexe, qui doit être fait en plusieurs étapes.

Étape 1, ajoutez un nouveau champ pour ForeignKey, en veillant à le marquer comme nul (notez que le modèle auquel nous sommes liés est également maintenant inclus):

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)

... et créer une migration pour ce changement.

./manage.py makemigrations discography

Étape 2, remplissez votre nouveau champ. Pour ce faire, vous devez créer une migration vide.

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

Une fois que vous avez cette migration vide, vous souhaitez y ajouter une seule opération RunPython afin de lier vos enregistrements. Dans ce cas, cela pourrait ressembler à ceci:

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()

Maintenant que vos données sont transférées dans le nouveau champ, vous pouvez réellement le faire et tout laisser tel artist_link , en utilisant le nouveau champ artist_link pour tout. Ou, si vous souhaitez effectuer un peu de nettoyage, vous souhaitez créer deux autres migrations.

Pour votre première migration, vous souhaitez supprimer votre champ d'origine, artist . Pour votre deuxième migration, renommez le nouveau champ artist_link en artist .

Cela se fait en plusieurs étapes pour s'assurer que Django reconnaît correctement les opérations.