manytomany many foreign example django foreign-keys migration manytomanyfield

many - Error de migración de Django: no puede alterar desde o hacia campos M2M, o agregar o eliminar a través de=en campos M2M



manytomany django (4)

Estoy tratando de modificar un campo M2M a un campo ForeignKey. El comando validar no me muestra problemas y cuando ejecuto syncdb:

ValueError: Cannot alter field xxx into yyy they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)

Así que no puedo hacer la migración.

class InstituteStaff(Person): user = models.OneToOneField(User, blank=True, null=True) investigation_area = models.ManyToManyField(InvestigationArea, blank=True,) investigation_group = models.ManyToManyField(InvestigationGroup, blank=True) council_group = models.ForeignKey(CouncilGroup, null=True, blank=True) #profiles = models.ManyToManyField(Profiles, null = True, blank = True) profiles = models.ForeignKey(Profiles, null = True, blank = True)

Este es mi primer proyecto de Django, así que cualquier sugerencia es bienvenida.


Me tropecé con esto y aunque no me importaban mucho mis datos, todavía no quería eliminar toda la base de datos. Así que abrí el archivo de migración y cambié el AlterField() a un RemoveField() y un AddField() que funcionó bien. Perdí mis datos en el campo específico, pero nada más.

Es decir

migrations.AlterField( model_name=''player'', name=''teams'', field=models.ManyToManyField(related_name=''players'', through=''players.TeamPlayer'', to=''players.Team''), ),

a

migrations.RemoveField( model_name=''player'', name=''teams'', ), migrations.AddField( model_name=''player'', name=''teams'', field=models.ManyToManyField(related_name=''players'', through=''players.TeamPlayer'', to=''players.Team''), ),


Posibles soluciones:

  • Cree un nuevo campo con la relación ForeignKey llamada profiles1 y NO modifique los profiles . Realiza y ejecuta la migración. Es posible que necesite un parámetro related_name para evitar conflictos. Hacer una migración posterior que suelte el campo original. Luego realice otra migración que cambie el nombre de profiles1 a profiles . Obviamente, no tendrá datos en el nuevo campo ForeignKey.

  • Escriba una migración personalizada: https://docs.djangoproject.com/en/1.7/ref/migration-operations/

Es posible que desee utilizar makemigration y la migration lugar de syncdb .

¿Tiene su InstituteStaff datos que desea conservar?


Si aún está desarrollando la aplicación y no necesita conservar sus datos existentes, puede solucionar este problema haciendo lo siguiente:

  1. Eliminar y volver a crear la db.

  2. Ve a tu carpeta de proyecto / aplicación / migraciones

  3. Elimine todo en esa carpeta con la excepción del archivo init .py. Asegúrate de eliminar también el directorio de pycache .

  4. Ejecute syncdb, makemigrations y migre.


Yo diría: ¡Si la máquina no puede hacer algo por nosotros, entonces ayudémoslo!

Debido a que el problema que OP pone aquí puede tener múltiples mutaciones, trataré de explicar cómo luchar con ese tipo de problema de una manera sencilla.

Supongamos que tenemos un modelo (en la aplicación llamado users ) como este:

from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person) def __str__(self): return self.name

pero después de un tiempo necesitamos agregar una fecha de ingreso a un miembro. Así que queremos esto:

class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through=''Membership'') # <-- through model def __str__(self): return self.name # and through Model itself class Membership(models.Model): person = models.ForeignKey(Person, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField()

Ahora, normalmente tendrás el mismo problema que escribió OP. Así que en ese caso volvemos a lo que escribí al principio, ayudando así a la máquina. Podemos lograr ese objetivo en los siguientes pasos:

  • empezar desde este punto:

    from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person) def __str__(self): return self.name

  • cree a través del modelo y ejecute python manage.py makemigrations ( pero no ponga propiedad a through del campo Group.members todavía ):

    from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person) # <-- no through property yet! def __str__(self): return self.name class Membership(models.Model): # <--- through model person = models.ForeignKey(Person, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField()

  • cree una migración vacía con los python makemigrations users --empty command y cree un script de conversión en python (más información sobre las migraciones de python here ) que crea nuevas relaciones ( Membership ) para un campo antiguo ( Group.members ). Podría verse así:

    # Generated by Django A.B on YYYY-MM-DD HH:MM import datetime from django.db import migrations def create_through_relations(apps, schema_editor): Group = apps.get_model(''users'', ''Group'') for group in Group.objects.all(): for member in group.members.all(): Membership( person=member, group=group, date_joined=datetime.date.today() ).save() class Migration(migrations.Migration): dependencies = [ (''myapp'', ''0005_create_models''), ] operations = [ migrations.RunPython(create_through_relations, reverse_code=migrations.RunPython.noop), ]

  • elimine el campo de members en el modelo de Group y ejecute las python manage.py makemigrations , para que nuestro Group se vea así:

    class Group(models.Model): name = models.CharField(max_length=128)

  • agregue members campo del modelo de Group , pero ahora con propiedad y ejecute python manage.py makemigrations :

    class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through=''Membership'')

¡y eso es! Ahora necesita cambiar la creación de miembros de una nueva forma en su código: a través del modelo. Más sobre here .