I have a unmanaged model Client
class Client(models.Model):
client_id = models.IntegerField('ID', primary_key=True)
name = models.CharField()
class meta:
manage = False
I use Client to extend User:
class Account(models.Model):
user = models.OneToOneField(User)
client = models.OneToOneField(Client, to_field='client_id')
I thought Django will create foreign key reference to Client.client_id instead of Client.id even without explicit to_field='client_id' because of the definition of Client model. But sqlmigrate shows:
BEGIN;
CREATE TABLE `pubsite_account` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `deg_client_id` integer NOT NULL UNIQUE, `user_id` integer NOT NULL UNIQUE);
ALTER TABLE `pubsite_account` ADD CONSTRAINT pubsite_account_deg_client_id_73086fddd308cd6f_fk_Clients_id FOREIGN KEY (`deg_client_id`) REFERENCES `Clients` (`id`);
ALTER TABLE `pubsite_account` ADD CONSTRAINT pubsite_account_user_id_33ed558985f73b32_fk_auth_user_id FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
COMMIT;
And nothing changes with setting to_field='client_id'. Any thoughts would be appreciated.
Django version: 1.8, 1.7 (Yep, I tried both)
Databse: mysql
I cant try right now but I think db_column is what you are looking for
client = models.OneToOneField(Client, db_column='client_id')
After discuss in #django-dev, it turns out to be a bug.
While a ticket has been opened, a developer MarkusH offers a temporary work around:
change managed = False on the model to =True
once you have new migration files, change the managed option on the model back to False
and in the corresponding migration file add 'managed': False, to the options array in the CreateModel operation.
-------edit---------
From the ticket page, this bug has been fixed. So if you come to here for the same thing, just update Django.
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 working with a new Django project which need to load data from a legacy db, but saving new model object always fails with IntegrityError: null value in column "id" violates not-null constraint after I loaded data from the legacy db.
Primary key in legacy db is in range from 10000 to 200000, the new db is Postgres 9.5 and never manual set SQL schema on it.
My model could be simple like:
class MyModel(Model):
id = IntegerField(primary_key=True)
This will fails when I run MyModel().save() or MyModel.create(). It's OK to run MyModel(id=233).save() like I used at loading data.
I guess it's because it does not know where to start to auto generate primary key from. How to fix this?
To add an auto-increment field in django, you are supposed to use AutoField
You should define your id field like this:
id = models.AutoField(primary_key=True)
If you want to name it as id, you are not required to define the field, django does that for you.
A model without explicit id field will still have a AutoField id as a primary key.
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'")
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.
I have two models: UserProfile (extended from user) and Cv. I created another model that have two foreign key that come from theses models.
class cv(models.Model):
user = models.ForeignKey(User, unique=True)
cv_d= models.TextField(max_length=1100)
...
class cvv(models.Model):
user = models.ForeignKey(User)
cv= models.ForeignKey(cv)
date = models.DateTimeField(auto_now=True)
In my view, I am trying to insert value on cvv:
...
obj = cv.objects.get(pk=id,active=True)
add=cvv(user=request.user, cv=obj)
add.save()
But, I am getting the following error:
(1452, 'Cannot add or update a child row: a foreign key constraint fails
How can I insert theses 2 foreign key on my model?
Welcome to one of the many reasons why you shouldn't use MySQL. This happens most often when you have one table that is MyISAM and one table that is InnoDB. Since myISAM doesn't support FK constraints all hell breaks loose when django creates a FK between the tables.
The fix is to either make both tables InnoDB or MyISAM and not to mix them. Or even better drop the bad RDMS for something not MySQL.