Why is unmanaged model not calculating id in Django? - django

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.

Related

How to add "ON DELETE" rules to existing column in a PostgreSQL database table?

I'm using PostgreSQL in a Django project. Django does not support "on delete" rules at the database level. At the application level it allows this parameter when setting a ForeignKey for a model, but it's only used to emulate the behavior when deleting instances. I'm trying to run a data migration that deletes a set of rows from a table which is reference by another one. The models look something like this:
class Album(models.Model):
name = models.CharField(max_length=128)
# ...
class Track(models.Model):
name = models.CharField(max_length=128)
album = models.ForeignKey(Album, related_name='tracks', null=True, on_delete=models.SET_NULL)
# ...
I don't know if this behavior is supposed to be emulated in delete calls performed on querysets, or only model instances. For me neither is working. The cleanest solution in my mind would be to add a RunSQL that adds a "ON DELETE SET NULL" rule on the Track.album foreign key at the database level (before the RunPython that actually tries to delete the Album rows). The problem is that Django seems to create a foreign key constraint with a dynamic name, so if I drop that constraint by name and create another one, I'm afraid the migration may fail when I deploy. Isn't there a simple way to add the rule (or drop/create the constraint) by column name?

Django ORM cannot auto set primary key for model after loading data from legacy db

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.

Why does Django set the pk of all my models to '90'?

I'm running Django 1.5 with SQLite, and I have a model called Assignment. Whenever I create one, it gets created with the correct pk value. But, whenever I try to retrieve any Assignment from my database, it is always returned with a pk of 90. I've been fighting this for an hour, and I have to admit I'm completely confused.
Here's my code, if it's any use.
class Assignment(models.Model):
class Meta:
app_label = 'holiday'
unique_together = ('year', 'employee')
year = models.PositiveIntegerField(db_index=True)
employee = models.ForeignKey('bsc.Employee', db_index=True)
days = models.PositiveIntegerField(null=True)
This, and a bunch of methods that calculate some values based on models related to this one. Nothing fancy.
I've got to add that this model has had a somewhat rough past - with all my absent-mindedness, I had originally set year as the primary key, which quickly failed as soon as I added two Assignments to different employees. Maybe I should look at the DB schema and see if anything's wrong. Thankfully, the app hasn't made it to production yet, but hopefully this can be fixed without a full DB reset.
If you had created 90 previous records then deleted the rows from your database; your database key index will still be set to what would have been the next primary key number in your database.
The way to resolve this would be to as described in this other stackoverflow post:
SQLite Reset Primary Key Field

Constraint trouble with concrete base models after migrating Django from MySQL to PostgreSQL

I'm attempting a migration from MySQL to PostgreSQL, and now I'm having trouble with concrete base classes. I have code similar to this:
class BaseKlass(models.Model):
name = CharField(max_length = 64)
class SomeKlass(BaseKlass):
value = IntegerField()
Whenever I create an instance of SomeKlass, I get an error like this:
IntegrityError: null value in column "baseklass_ptr_id" violates not-null constraint
I looked at the SQL being executed, and indeed the value for baseklass_ptr_id was null.
Any idea?
Setting an owner for the id sequence solved the problem:
ALTER SEQUENCE myapp_baseklass_id_seq OWNED BY myapp_baseklass.id;

Django Two foreign key

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.