132👍
I stumbled upon this and although I didn’t care about my data much, I still didn’t want to delete the whole DB. So I opened the migration file and changed the AlterField()
command to a RemoveField()
and an AddField()
command that worked well. I lost my data on the specific field, but nothing else.
I.e.
migrations.AlterField(
model_name='player',
name='teams',
field=models.ManyToManyField(related_name='players', through='players.TeamPlayer', to='players.Team'),
),
to
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'),
),
94👍
NO DATA LOSS EXAMPLE
I would say: If machine cannot do something for us, then let’s help it!
Because the problem that OP put here can have multiple mutations, I will try to explain how to struggle with that kind of problem in a simple way.
Let’s assume we have a model (in the app called users
) like this:
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
but after some while we need to add a date of a member join. So we want this:
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()
Now, normally you will hit the same problem as OP wrote. To solve it, follow these steps:
-
start from this point:
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
-
create through model and run
python manage.py makemigrations
(but don’t putthrough
property in theGroup.members
field yet):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()
-
create an empty migration using
python manage.py makemigrations users --empty
command and create conversion script in python (more about the python migrations here) which creates new relations (Membership
) for an old field (Group.members
). It could look like this:# 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') Membership = apps.get_model('users', 'Membership') 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), ]
-
remove
members
field in theGroup
model and runpython manage.py makemigrations
, so ourGroup
will look like this:class Group(models.Model): name = models.CharField(max_length=128)
-
add
members
field the theGroup
model, but now withthrough
property and runpython manage.py makemigrations
:class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership')
and that’s it!
Now you need to change creation of members in a new way in your code – by through model. More about here.
You can also optionally tidy it up, by squashing these migrations.
- [Django]-Django select only rows with duplicate field values
- [Django]-How to filter empty or NULL names in a QuerySet?
- [Django]-Get last record in a queryset
24👍
Potential workarounds:
-
Create a new field with the ForeignKey relationship called
profiles1
and DO NOT modifyprofiles
. Make and run the migration. You might need arelated_name
parameter to prevent conflicts. Do a subsequent migration that drops the original field. Then do another migration that renamesprofiles1
back toprofiles
. Obviously, you won’t have data in the new ForeignKey field. -
Write a custom migration: https://docs.djangoproject.com/en/1.7/ref/migration-operations/
You might want to use makemigration
and migration
rather than syncdb
.
Does your InstituteStaff
have data that you want to retain?
- [Django]-What is the right way to validate if an object exists in a django view without returning 404?
- [Django]-How to use 'select_related' with get_object_or_404?
- [Django]-Troubleshooting Site Slowness on a Nginx + Gunicorn + Django Stack
21👍
If you’re still developing the application, and don’t need to preserve your existing data, you can get around this issue by doing the following:
-
Delete and re-create the db.
-
go to your project/app/migrations folder
-
Delete everything in that folder with the exception of the init.py file. Make sure you also delete the pycache dir.
-
Run syncdb, makemigrations, and migrate.
- [Django]-How to define two fields "unique" as couple
- [Django]-How to Unit test with different settings in Django?
- [Django]-Render HTML to PDF in Django site
4👍
Another approach that worked for me:
- Delete the existing M2M field and run migrations.
- Add the FK field and run migrations again.
FK field added in this case has no relation to the previously used M2M field and hence should not create any problems.
- [Django]-AssertionError: database connection isn't set to UTC
- [Django]-Querying django migrations table
- [Django]-Malformed Packet: Django admin nested form can't submit, connection was reset
1👍
This link helps you resolve all problems related to this
The one which worked for me is python3 backend/manage.py migrate –fake "app_name"
- [Django]-Django migration strategy for renaming a model and relationship fields
- [Django]-Jquery template tags conflict with Django template!
- [Django]-Django auto_now and auto_now_add
1👍
I literally had the same error for days and i had tried everything i saw here but still didn’y work.
This is what worked for me:
- I deleted all the files in migrations folder exceps init.py
- I also deleted my database in my case it was the preinstalled db.sqlite3
After this, i wrote my models from the scratch, although i didn’t change anything but i did write it again. - Apply migrations then on the models and this time it worked and no errors.
- [Django]-Django: list all reverse relations of a model
- [Django]-Redirect to named url pattern directly from urls.py in django?
- [Django]-Getting the SQL from a Django QuerySet
1👍
This worked for Me as well
- Delete last migrations
- run command
python manage.py migrate --fake <application name>
- run command ‘python manage.py makemigrations ‘
- run command ‘python manage.py migrate’
Hope this will solve your problem with deleting database/migrations
- [Django]-Google Static Maps URL length limit
- [Django]-Explicitly set MySQL table storage engine using South and Django
- [Django]-Django – Clean permission table
1👍
-
First delete the migrations in your app (the folders/ files under ‘migrations’
folder)
Showing the ‘migrations’ folder -
Then delete the ‘db.sqlite3’ file
Showing the ‘db.sqlite3’ file -
And run
python manage.py makemigrations name_of_app
-
Finally run
python manage.py migrate
- [Django]-How to add multiple objects to ManyToMany relationship at once in Django ?
- [Django]-How to disable admin-style browsable interface of django-rest-framework?
- [Django]-Django FileField with upload_to determined at runtime
1👍
Django >3.0 has explicitly introduced a migration operation for this with no data loss: SeparateDatabaseAndState It uses the fact the Django has already natively implemented a M2M table. The only challenge is that you need to get the information, how the M2M table is implemented by Django behind your visible models.py.
Taking the example from @wannaryytel:
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person)
- Introduce your wished table in
models.py
but respect the used names of Django for the naming convention of the foreign key fields (model Person translates to person). Further, tell Django to use the existing M2M table with the naming convention<app>_<model_name>_<m2m_field_name>
:
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
class Meta:
db_table = "application_group_members"
- Run
python manage.py makemigrations
and modify the migration filexxxx_migration.py
by putting all original operations inside Djangos new operationmigrations.SeparateDatabaseAndState
class Migration(migrations.Migration):
dependencies = [("your_app", "0127_previous"),]
operations = [
migrations.SeparateDatabaseAndState(
state_operations=[
# the list which was originally directly under operations
# ...
]
)
]
- Run
migrate
. Now you have the M2M table in your models and it is synched with the database.
From here on, you can now modify the field names, add additional fields and so on with the conventional migration methods.
- [Django]-Django model CharField: max_length does not work?
- [Django]-How can I temporarily disable a foreign key constraint in MySQL?
- [Django]-How can I get the full/absolute URL (with domain) in Django?
0👍
I had the same problem and found this How to Migrate a ‘through’ to a many to many relation in Django article which is really really helped me to solve this problem. Please have a look. I’ll summarize his answer here,
There is three model and one(CollectionProduct
) is going to connect as many-to-many relationship.
This is the final output,
class Product(models.Model):
pass
class Collection(models.Model):
products = models.ManyToManyField(
Product,
blank=True,
related_name="collections",
through="CollectionProduct",
through_fields=["collection", "product"],
)
class CollectionProduct(models.Model):
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
class Meta:
db_table = "product_collection_products"
and here is the solution,
The solution
Take your app label (the package name, e.g. ‘product’) and your M2M field name, and combine them together with and underscore:
APPLABEL + _ + M2M TABLE NAME + _ + M2M FIELD NAME
For example in our case, it’s this:
product_collection_products
This is your M2M’s through database table name. Now you need to edit your M2M’s through model to this:
Also found another solution in In Django you cannot add or remove through= on M2M fields article which is going to edit migration files. I didn’t try this, but have a look if you don’t have any other solution.
- [Django]-Best practice for Django project working directory structure
- [Django]-Django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb
- [Django]-How to filter empty or NULL names in a QuerySet?
0👍
this happens when adding ‘through’ attribute to an existing M2M field:
as M2M fields are by default handled by model they are defined in (if through is set).
although when through is set to new model the M2M field is handled by that new model, hence the error in alter
solutions:-
you can reset db or
remove those m2m fields and run migration as explained above then create them again
- [Django]-How to pass multiple values for a single URL parameter?
- [Django]-Add inline model to django admin site
- [Django]-Django Installed Apps Location
0👍
*IF YOU ARE IN THE INITIAL STAGES OF DEVELOPMENT AND CAN AFFORD TO LOOSE DATA 🙂
delete all the migration files except init.py
then apply the migrations.
python manage.py makemigrations
python manage.py migrate
this will create new tables.
- [Django]-Is it better to use path() or url() in urls.py for django 2.0?
- [Django]-Specifying limit and offset in Django QuerySet wont work
- [Django]-"gettext()" vs "gettext_lazy()" in Django