ProgrammingError at /app-name/url-name
relation "TableName" does not exist
LINE 1: SELECT (1) AS "a" FROM "TableName" WHERE "TableName..."
I have done an inspectdb, confirmed the mapping matches what is automatically set when running makemigrations, and deleted all migrations from the django_migrations table and re-ran migrate. I also checked that the migrations are successfully imported, by looking at the django_migrations table,as well as running showmigrations.
I wonder why I see the double quotes around the table names, is that why new models cannot be used? Interestingly, if I reference the model to be used in a form (not a view) it does seem to work okay, I see the correct inputs in the form coming from the database. The error happens when I query using Django - this query is setup within the same model 'TableName' itself, is that referenced correctly? (instead of doing importing TableName from app-name.models)
TableName.objects.using('CUSTOMDBSETTING').filter(colid='value')
Note that this works when I try using the shell directly, just not through Django. I also don't have a primary key for this table, and when I try setting up a non-default (not id), it gives me another error.
So it does give me the error when I try to reference what should be the primary key (but isn't) in the table mapping. When I try removing the primary key for the specific id (only in models, not in the migrations)
('42S22', "[42S22] [Microsoft][ODBC Driver 17 for SQL Server][SQL
Server]Invalid column name 'id'. (207) (SQLExecDirectW); [42S22]
[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Statement(s)
could not be prepared. (8180)")
So, the answer to this question is that if one doesn't assign a specific unique/primary key in the model in question, the default 'id' mapped in Django would apply.
That is, expect your migrations to have a primary key like this (the model mapping wouldn't explicitly show this):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
...
]
To fix this issue, either use the primary key 'id' from Django or setup a primary key - doesn't have to done for the actual table, just the Django model. Then re-run the migrations and make sure they applied to catch this change...
Now, migrations should look like this (and no 'id' key would be used)
('tableid', models.CharField(blank=True, db_column='TableID', max_length=255, primary_key=True, serialize=False)),
or something like this if it's auto incremented
customid = models.AutoField(db_column='CustomID', null=False, primary_key=True, max_length=10)
Related
I have an unmanaged model in Django:
class Person(models.Person):
name = models.CharField(max_length=200)
class Meta:
managed = False
db_table = '"public"."person"'
Somewhere in my tests, I try to create a Person entry in the DB:
person = Person(name="Ariel")
person.save()
But then I get an error:
django.db.utils.IntegrityError: null value in column "id" of relation "person" violates not-null constraint
DETAIL: Failing row contains (null, Ariel).
Outside tests, everything works fine. In the tests, I initialize the DB with the tables referenced by the unmanaged by loading a schema dump.
The Django docs states that "no database table creation, modification, or deletion operations will be performed for this model", and that "all other aspects of model handling are exactly the same as normal", including "adding an automatic primary key field to the model if you don’t declare it". But doesn't that mean this code should work? How come Django and Postgres are not taking care of the id? Am I doing something wrong? How can I fix it?
Surely the issue that you're having is that in your PostgreSQL table, id is not an auto incremental field and it nulls by default.
It's quite a common issue when using unmanaged models on Django. You need to cover every single aspect of the table you're using.
I'm using Django 3.0.2 and sqlite3 DB.
I set following simple models:
from django.db import models
class Description(models.Model):
IDENTIFIER_LENGTH = 30
identifier = models.CharField(max_length=IDENTIFIER_LENGTH, blank=False, unique=True, primary_key=True)
Strangely, the unique=True seems not working. Following code run in shell mode
from testunique.models import Description
object = Description('first-object')
object.save()
object.save()
doesn't raise any error. For the record, here is the SQL code of the migrations:
BEGIN;
--
-- Create model Description
--
CREATE TABLE "testunique_description" ("identifier" varchar(30) NOT NULL PRIMARY KEY);
COMMIT;
What is wrong here? Thanks for the answer.
Django considers records with a set primary key as records already in the database. Therefore it will not perform a INSERT … query, but an UPDATE …. It is sometimes used as a trick to set the primary key in Django to None to make a copy of a given record (since then Django will make another INSERT … query).
You can force insertion with:
Description.objects.create(name='first-object')
Description.objects.create(name='first-object') # raises an error
or you can work with force_insert=True:
Description(name='first-object').save(force_insert=True)
Description(name='first-object').save(force_insert=True) # raises an error
I have a model with a foreign key field. I want to remove the foreign key reference. However, migration fails because of the following error:
Cannot delete or update a parent row: a foreign key constraint fails
I understand what is going on, but I don't know how to resolve this properly with Django. Right now (since I'm at the beginning of my project), I go into the MySQL database manually and delete the tables and re-migrate as if it was the first migration.
Is there a way, using Django, to get around this foreign key constraint issue?
I'm using Django 1.7
Database backend is MySQL
EDIT - Models Before/After migrations
Before:
class Skills(models.Model):
# fields here...
class Project(models.Model):
skills = models.ForeignKey(Skills, verbose_name = "Required Skills", blank = True, null = True)
After:
class Skill(models.Model):
# fields here...
class Project(models.Model):
skills = models.ForeignKey(Skill, verbose_name = "Required Skills", blank = True, null = True)
I'm pretty sure all I've done is removed the "Plural" from the Skill model. The the makemigrations command works fine, but the migrate command fails with the above noted error.
EDIT 2
Hit the same error:
Cannot drop column 'skills_id': needed in a foreign key constraint 'projects_project_skills_id_4cc7e00883ac4de2_fk_projects_skill_id'
This time I dropped the field skill from model Project
A little hack I used:
Add a migration operations that first alters the field to say IntegerField before other operations i.e
operations = [
migrations.AlterField(
model_name='projects_project',
name='skills',
field=models.IntegerField(default=0)
),
..... other migration entries now after this.
]
This is my SOLUTION (do this manually first)
ALTER TABLE forms_formentry DROP FOREIGN KEY
forms_formentry_form_id_d0f23912_fk_forms_form_page_ptr_id
This is the ERROR
django.db.utils.OperationalError: (1833, "Cannot change column 'page_ptr_id': used in a foreign key constraint 'forms_formentry_form_id_d0f23912_fk_forms_form_page_ptr_id' of table 'dbname.forms_formentry'")
when I am useing django.db.backends.postgresql_psycopg2 and running manage.py syncdb, following error raised
django.db.utils.ProgrammingError: multiple primary keys for table "token_place" are not allowed
LINE 3: "signatureid" integer NOT NULL PRIMARY KEY REFERENCES "s...
model:
class TokenPlace(models.Model):
token = models.ForeignKey(Token, db_column='tokenid', primary_key=True)
signature = models.ForeignKey(Signature, db_column='signatureid', primary_key=True)
place = models.IntegerField(primary_key=True)
class Meta:
db_table = 'token_place'
my models work correctly with mysql but I must deploy it in postgres
how to fix this problem?
After reading your answer I finally get the question, you are looking for composite keys in Django. Unfortunately this is not supported by Django yet. If you need it there are a few options:
Try the Django Composite Key project: https://github.com/simone/django-compositekey
Use the patches and explanation given on this page to add the support to Django: https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys
Use SQLAlchemy (http://www.sqlalchemy.org/) for querying as it does support this properly.
Use a single primary key column in Django and read/write from/to a writable view which communicates with the actual table in the background.
I'm switching from a MySQL backend to a PostgreSQL backend and am running into some model inheritance issues. Here is an example of the models:
class Parent(models.Model):
key = models.Charfield(...)
value = models.Charfield(...)
content_type = models.ForeignKey(ContentType)
object_id = models.CharField(max_length=200)
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Child1(Parent):
pass
class Child2(Parent):
pass
The reason we have two child classes like this is, we're simulating two key/value pairs in another model, and wanted to separated them into two tables for an easier lookup. The Generic FKs were also for attaching this to other models. This inheritance setup works fine in MySQL, but when I switched it to PostgreSQL, I get an error when trying to run our tests (but syncdb works fine). It's as if Django is OK with the relationship but PostgreSQL doesn't like the SQL being generated. When I look at what's being generated from syncdb I see this:
CREATE TABLE "myapp_parent" (
"id" serial NOT NULL PRIMARY KEY,
"key" varchar(200) NOT NULL,
"value" varchar(200) NOT NULL,
"content_type_id" integer NOT NULL REFERENCES "django_content_type" ("id") DEFERRABLE INITIALLY DEFERRED,
"object_id" varchar(200) NOT NULL);
CREATE TABLE "myapp_child1" (
"parent_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "myapp_parent" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE TABLE "myapp_child2" (
"parent_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "myapp_parent" ("id") DEFERRABLE INITIALLY DEFERRED);
So everything looks right, then when I run my tests I get this:
Error: Database test_myapp couldn't be flushed. Possible reasons:
* The database isn't running or isn't configured correctly.
* At least one of the expected database tables doesn't exist.
* The SQL was invalid.
Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run.
The full error: column "id" of relation "myapp_child1" does not exist
When I run flush:
SELECT setval(pg_get_serial_sequence('"myapp_child1"','id'), 1, false);
I've tried manually adding an ID field as the primary key in the child model but Django throws an error saying it conflicts with the Parent's ID field. How do I fix this so PostgreSQL likes it? And thanks in advance.
If you're using model inheritance in django, you should declare class Parent to be abstract
class Parent(models.Model):
...
class Meta:
abstract = True
See the docs. I imagine that some postgres / mysql differences have only been tested against standard conforming code - which could be why you're having problems here. I'd also recommend ./manage.py syncdb after making these changes ;-)
If in doubt, and on in a testing environment, you can drop your tables and start again with
$ ./manage.py sqlclear | ./manage.py dbshell
Your model must contain one - and only one - foreign key to the target model. If you have more than one foreign key, a validation error will be raised. This is one of the restrictions of django.