I normally find a solution around this problem. I even tried the nuclear option of resetting the data base completely with python manage.py flush but no luck. (I have also tried by deleting the migrations folder, but again no result)
the exact error message is the following:
column main_reviewrating.venue_id does not exist
Maybe it's the first time I pay attention to this but the venue**_id** seems strange.
I am quite sure the usual message would have something like
main_reviewrating.venue (without the _id
When I run python manage.py showmigrations <your_app_name> it does show
[X] 0001_initial
I should also add that I am running this on my local, so no problem specific to deployment.
Here is the code (models.py)
class Venue(models.Model):
name = models.CharField(verbose_name="Name",max_length=100, null=True, blank=True)
def __str__(self):
return str(self.name) if self.name else ''
class Product(models.Model):
name = models.CharField('Product Name', max_length=120, null=True)
class Meta:
db_table='Product'
def __str__(self):
return str(self.name)
class ReviewRating(models.Model):
user = models.ForeignKey(User,blank=True, on_delete=models.CASCADE, related_name="usercomments")
product=models.ForeignKey(Product,related_name="comments", on_delete=models.CASCADE)
review =models.TextField(max_length=250)
rating =models.IntegerField(choices=RATING, default=0)
venue = models.ForeignKey(Venue, blank=True, null=True, related_name="venues", on_delete=models.CASCADE)
def __str__(self):
return '%s - %s'%(self.user, self.product)
Any idea what I am doing wrong?
Edit: on a second thought, maybe I am using the ForeignKey wrong. What I am trying to do here is to link a specific review, of a specific product to a specific venue.
This means, the same product could be reviewed by the same user in a different venue.
1.Delete your database like something.sqlite3 (for backup you may rename it).
2.Delete all migration file except __init__.py.
3.Run the migrations command again.
Hopefully you will get no issue.
Delete all files in migration folder except init.py file in your app folder and the run makemigrations.
I have a simple view on the DB which selects from other DB's tables located on the same MSSQL Server to ultimately serve the collected info as a dropdown to the user.
So far I've added the Model with inspectdb:
class AutPricePlanView(models.Model):
priceplan_name = models.CharField(db_column='PricePlan', max_length=50, blank=True, unique=True)
class Meta:
managed = False # Created from a view. Don't remove.
db_table = 'AUT_PricePlanView'
Also I have a second existing (Django Native) Model where I want to use the values from the view for a Dropdown Field (to keep everything in sync):
class PricePlanDownload(models.Model):
requesting_user = models.CharField(blank=True, default=None, max_length=50, null=True)
requested_at = models.DateTimeField(auto_now_add=True)
document = models.FileField(upload_to='documents/price_plan_uploads/%Y/%m/%d', blank=True)
priceplan = models.ForeignKey(AutPricePlanView, null=True, on_delete=models.DO_NOTHING)
Makemigrations works fine but when I try to actually migrate I get the following issue: (shortened it a little bit)
django.db.utils.ProgrammingError: ('42000', "[42000] [FreeTDS][SQL Server]Foreign key references object 'AUT_PricePlanView' which is not a user table. (1768) (SQLExecDirectW)")
I would be really grateful if someone had an idea or a workaround since I can't figure out what the heck this has to do with a "user" table...
Since the view is not actually a table, you cannot set Foreign Key constraints. Since ForeignKey's default db_constraint value is True, Django tries to set Foreign Key constraints when performing migrations. This is the reason the migration fails.
So, you can turn off the db_constraint option. And you can remove the existing migration file, and re-create the migration file. Then, the migration will success and you can keep everything in sync.
class PricePlanDownload(models.Model):
... other fields ...
priceplan = models.ForeignKey(AutPricePlanView, null=True, on_delete=models.DO_NOTHING, db_constraint=False)
Pro Tip: You can review migration's SQL using python manage.py sqlmigrate <appname> <migration number>, like python manage.py sqlmigrate yourapp 0002.
Update: You can define __str__ to display the correct value at the dropdown menu.
class AutPricePlanView(models.Model):
priceplan_name = models.CharField(db_column='PricePlan', max_length=50, blank=True, unique=True, primary_key=True)
# null=False by default. See https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L132
def __str__(self):
return self.priceplan_name
class Meta:
managed = False # Created from a view. Don't remove.
db_table = 'AUT_PricePlanView'
In Django (2.x) I have an entry form, the model is here:
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
class Sample(models.Model):
sample_id = models.AutoField(primary_key=True)
area_easting = models.IntegerField()
area_northing = models.IntegerField()
context_number = models.IntegerField()
sample_number = models.IntegerField()
# taken_by = models.IntegerField()
taken_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.PROTECT)
def __str__(self):
return str(self.sample_id)
class Meta:
db_table = 'samples\".\"sample'
#ordering = ["sample_id"]
managed = False
#verbose_name_plural = "samples"
This works as expected, a list of usernames drops down (while I would like to format - firstname lastname). However, when I return to the main viewing page I see an error.
django.db.utils.ProgrammingError: column sample.taken_by_id does not exist
LINE 1: ...text_number", "samples"."sample"."sample_number", "samples"....
^
HINT: Perhaps you meant to reference the column "sample.taken_by".
Clearly Django is adding the _id to the table name causing the error, I expect because it is a foreign key.
Any ideas how to remedy this behaviour?
You can explicitly set the underlying db column via the db_column attribute:
taken_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column='taken_by', on_delete=models.PROTECT)
https://docs.djangoproject.com/en/2.1/ref/models/fields/#database-representation
^ link to the docs where it specifies that it creates a _id field.
based from the error message you have posted. It seems that your database schema is not updated.
you might need to do manage makemigrations and migrate to apply your model changes to your db schema
e.g
$ python manage.py makemigrations
# to apply the new migrations file
$ python manage.py migrate
I'm trying to modify a M2M field to a ForeignKey field. The command validate shows me no issues and when I run 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)
So I can't make the migration.
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)
Any suggestions?
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'),
),
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 put through property in the Group.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 the Group model and run python manage.py makemigrations, so our Group will look like this:
class Group(models.Model):
name = models.CharField(max_length=128)
add members field the the Group model, but now with through property and run python 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.
Potential workarounds:
Create a new field with the ForeignKey relationship called profiles1 and DO NOT modify profiles. Make and run the migration. You might need a related_name parameter to prevent conflicts. Do a subsequent migration that drops the original field. Then do another migration that renames profiles1 back to profiles. 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?
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.
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.
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"
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.
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
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
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.
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
*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.
I changed my model from this:
class DistList(models.Model):
creator = models.ForeignKey(User, related_name='creator')
created_date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=200, unique=True)
description = models.TextField(blank=True, null=True)
company = models.ForeignKey(Company, blank=True, null=True)
To this:
class DistList(models.Model):
creator = models.ForeignKey(User, related_name='creator')
created_date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=200, unique=True)
description = models.TextField(blank=True, null=True)
company = models.ForeignKey(Company)
The only change was turning the company FK relationship from not required to required.
When I run the migration I specify a one off value that corresponds to the pk of the first company.
./manage.py schemamigration distlist --auto
? The field 'DistList.company' does not have a default specified, yet is NOT NULL.
? Since you are making this field non-nullable, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? Please select a choice: 2
? Please enter Python code for your one-off default value.
? The datetime module is available, so you can do e.g. datetime.date.today()
>>> 1
But when I run the migration I get an error because it has a pending trigger event?
./manage.py migrate distlist
Running migrations for distlist:
- Migrating forwards to 0005_auto__chg_field_distlist_company.
> distlist:0005_auto__chg_field_distlist_company
FATAL ERROR - The following SQL query failed: ALTER TABLE "distlist_distlist" ALTER COLUMN "company_id" SET NOT NULL;
The error was: cannot ALTER TABLE "distlist_distlist" because it has pending trigger events
I'm not doing anything that seems weird from my point of view so I don't understand this error at all. Can anyone offer insight? I can post the full stack trace if it'll help but I feel like theres something obvious about south and postgresql that perhaps I'm missing?
So I believe I've found the answer. I think postgresql doesn't like altering schemas and adding data at the same time. I first created a datamigration:
./manage.py datamigration distlist add_default_values_to_existing_companies
Then I added this to the forwards method:
def forwards(self, orm):
"Write your forwards methods here."
for distlist in orm['distlist.Distlist'].objects.all():
distlist.company = orm['userprofile.Company'].objects.get(id=1)
distlist.save()
Then I altered the model to remove the blank and null from company.
Then I ran the schema migration and chose to specify a one off for the value as 1 (as I did in the question).
Then I edited that migration file thusly:
def forwards(self, orm):
# Changing field 'DistList.company'
# db.alter_column(u'distlist_distlist', 'company_id', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['userprofile.Company']))
db.alter_column(u'distlist_distlist', 'company_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['userprofile.Company']))
I just commented out the generated line and removed the default=1 arg.
I don't know... maybe this isn't right but it seemed to work. Hopefully this will help someone.