Multiple default values specified for column "id" of the table - python

I use to run my website on my laptop and its database was Sqlite, recently I wanted to transfer it to DigitalOcean and I changed its database to Postgresql, but when I migrate I encounters with some problems.
Python 3.4
Django 1.8
Error
django.db.utils.ProgrammingError: multiple default values specified for column "id" of table "profiles_userprofile"
My Model
class UserProfile(models.Model):
user = models.OneToOneField(User)
avatar = models.ImageField(blank=True, upload_to=get_image_path, default='/static/image/avatar/male.png')
age = models.IntegerField(default=4, validators=[MinValueValidator(3), MaxValueValidator(99)])
What should I do?

Try explicitly specifying the id field and marking it as the primary key:
class UserProfile(models.Model):
id = models.BigIntegerField(primary_key = True)
user = models.OneToOneField(User)
avatar = models.ImageField(blank=True, upload_to=get_image_path, default='/static/image/avatar/male.png')
age = models.IntegerField(default=4, validators=[MinValueValidator(3), MaxValueValidator(99)])
Django should automatically create a sequence for this field.
It may be that the User foreign key without an explicitly defined primary key is confusing the ORM, although that's just a theory.

If you are developing locally, and don't care about your migration history, and you just need a quick-fix, you could do this:
manage.py migrate <your app name> zero
Then delete the migration files except for the __init__.py in <your app name>.
Finally:
manage.py makemigrations <your app name>
manage.py migrate
A more complicated approach would be learning how to write and modify migration files to populate existing rows.

Related

django table onlineshop_product has no column named name

I work on an online shopping website project with the help of Django. and I'm a beginner in Django The following code provides a table of my database. It helps to add a product.
class Product(models.Model):
category = models.ForeignKey(Category,related_name='products', on_delete=models.CASCADE)
name = models.CharField(max_length=200,db_index=True)
slug = models.SlugField(max_length=200,db_index=True)
image = models.ImageField(upload_to='products/%y/%m/%d',blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
Shows me an error in the browser. This error shows me when I add a product inside the admin panel. It helps to add a product but when I add the product the following error occurs.
OperationalError at /admin/onlineshop/product/add/
table onlineshop_product has no column named name
When I did migration using the command:
python manage.py migrate
It shows:
Operations to perform: Apply all migrations: admin, auth,
contenttypes, onlineshop, sessions Running migrations: No migrations
to apply. Your models in app(s): 'onlineshop' have changes that are
not yet reflected in a migration, and so won't be applied. Run
'manage.py makemigrations' to make new migrations, and then re-run
'manage.py migrate' to apply them.
python manage.py makemigrations
It is impossible to add the field 'created' with 'auto_now_add=True'
to product without providing a default. This is because the database
needs something to populate existing rows.
Provide a one-off default now which will be set on all existing
rows
Quit and manually define a default value in models.py. Select
an option:
How to solve it?
It is well-known issue, refer here[django-doc] for this, it will be easy if you choose 1st option.
Choose 1st option:
Then, you will be shown something like this in your shell:
Select an option: 1
Please enter the default value now, as valid Python
You can accept the default 'timezone.now' by pressing 'Enter' or you can provide another value.
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
[default: timezone.now] >>>
Here, simply press Enter the field will be added to migration and your work is done then simply run migrate command. You can also check it in migration file.
Migration file
operations = [
migrations.AddField(
....
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
)
]
Edit:
Try this:
name = models.CharField(max_length=200,db_index=True,default='any_name')
Then run makemigrations and migrate.
Change your Product(...) class like this:
from django.db import models
from datetime import datetime
class Product(models.Model):
# ... all other fields
name = models.CharField(max_length=200, db_index=True, default='Name not provided')
created = models.DateTimeField(auto_now_add=True, null=True)
updated = models.DateTimeField(auto_now=True, null=True)
and run these commands in sequence:
python manage.py makemigrations your_app_name # app name is optional parameter if you have app then provide app name
python manage.py migrate
Although settings null = True is bad idea but this will solve your problem for now but if you want to fix this issue you can follow this post or this answer.
Update
If above solution is not working or facing some issue then do like this:
Note : In this approach you've to delete you database (sqlite).
Step - 1
Delete __pycache__ & migrations folders from all of your apps
Step - 2
Delete db.sqlite3
Step - 3
Run makemigrations & migrate commands as mentioned above.

Django creates a migration that seems already reflected in original postgresql schema

I've modified the foreign key calendar as nullable in my Django model CalendarAssign. \
# ---------------------------------------------------------------------------- #
class Calendars(models.Model):
id = models.CharField(primary_key=True, max_length=100)
cms_id = models.CharField(max_length=100)
default_program = models.ForeignKey(ControlPrograms, models.CASCADE, blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
managed = True
db_table = 'calendars'
# ---------------------------------------------------------------------------- #
class CalendarAssign(models.Model):
device_mac = models.ForeignKey(Device, models.CASCADE)
calendar = models.ForeignKey(Calendars, models.CASCADE, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
managed = True
db_table = 'calendar_assign'
When applying the migration generated by Django it gives me an error.
operations = [
migrations.AlterField(
model_name='calendarassign',
name='calendar',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='smartbridge.Calendars'),
)
Generated sql code uses unsupported feature 'WITH ORDINALITY'.
It's because Django doesn't support the Postrges version we are using.
WITH ORDINALITY appears in psql 9.4 but we use version 9.1.
Both Postgres and Django cannot be upgraded right now. So I need to write the migration manually (without 'WITH ORDINALITY' feature).
migrations.RunSQL("DO $$DECLARE r record;\
BEGIN\
FOR r IN SELECT table_name,constraint_name \
FROM information_schema.constraint_table_usage \
WHERE table_name IN ('calendars') AND constraint_name like '%calendar_assign_calendar_id%'\
LOOP\
EXECUTE 'ALTER TABLE calendar_assign DROP CONSTRAINT '|| quote_ident(r.constraint_name) || ';';\
END LOOP;\
ALTER TABLE calendar_assign ALTER COLUMN calendar_id DROP NOT NULL; \
ALTER TABLE calendar_assign \
ADD CONSTRAINT calendar_assign_calendar_id_fk_calendars_id FOREIGN KEY (calendar_id) REFERENCES calendars(id);\
END$$;")
Migration seems to work fine.
calendar is now nullable but Django still detect some difference.
If a ask Django to generate the migration corresponding to the difference it generates the same as before my manual migration.
I would like Django to see no difference after my migration.
Thanks
I think you will have to set managed = False for the time being, otherwise the makemigrations command will each time think it has not been made nullable yet.
The migration construction command looks to the previous migration files, and thus constructs a conceptual model how a table will look like in the database if all the previous migrations took place. Based on that model it will look for differences with your Django model that you constructed, and thus create a migration file for that.
As long as you thus do not migrate with the AlterField command, Django will think you did not make the field nullable. It can not parse SQL so even if you made it nullable over there, it will still assume that that the field is non-NULLable.
By setting it to managed=False [Django-doc], Django will no longer manage the migrations of that file. You can create an empty migration [Django-doc] with:
python3 manage.py makemigrations --empty
and use this to define SQL queries to perform on the table.

"BLOB/TEXT column used in key specification without a key length" error in Django

I have this model in my Django project:
class Institution(models.Model):
name = models.CharField(unique=True, max_length=100, blank=True)
description = models.TextField(max_length=500, null=True, blank=True)
def __str__(self):
return self.name
I run my project completely when I use SQLite ,but when I change my database engine to Mysql I got this error:
MySQLdb._exceptions.OperationalError: (1170, "BLOB/TEXT column 'name' used in key specification without a key length")
What I must to do?
I got this error because I was trying to create an index for a TextField. I didn't notice I had used TextField for my name field, I was supposed to use CharField.
class myModel(models):
name = models.TextField(max_length=80)
class Meta:
indexes = [ models.Index(fields=['name'])]
Here was my solution.
First, I deleted the migration file created when I added an index in my model for the first time and run python manage.py makemigrations
Second, I removed the index from my model.
class myModel(models):
name = models.TextField(max_length=80)
Third, I run python manage.py makemigrations. It showed "no changes detected".
Fourth, I run python manage.py migrate and I did not get the error again.
To successfully create the index, I had to change the TextField field to CharField and add the index again.
class myModel(models):
name = models.CharField(max_length=80)
class Meta:
indexes = [ models.Index(fields=['name'])]
Running makemigrations and migrate went fine and created the index successfully.
The solution is pretty simple, Just follow their steps.
1 - Dell all the files in the migration folder
2 - Then run the command "python manage.py makemigrations"
3 - Then run the command "python manage.py migrate"
OR
Do it by the help of a simple SQL-lite Query
Adding index Example
alter table test add index index_name(col1(255),col2(255));
Adding unique index Example
alter table test add unique index_name(col1(255),col2(255));

Django migration from dynamic fields

I've the following Django model:
class Apple(models.Model):
text = models.TextField()
I've already many records, and I'd like to add a subject field to the model, so it'll look like:
class Apple(models.Model):
text = models.TextField()
subject = models.CharField(max_length = 128)
. In this case I run a makemigrations, but since subject can be empty, I need to set a default value either in the model, or in the migration file.
What would be the correct procedure if I'd like to take the subject from the text for the already existing database lines (for instance: text[:64])?
My solution would be to create a migration with a default value, run a management command to update the values, and with a new migration remove the default value for the subject. Is there a better solution? What is it? Can I somehow combine / do this in the migration itself?
Python: 3.4.5
Django: 1.9.2
For some databases including postgresql, it can be quicker to add a nullable field, therefore I would change your approach to:
schema migration creates the field with null=True (no need to set a default)
data migration populates the field
schema migration removes null=True from field
You can combine the three operations in one migration file. However the Django docs for data migrations recommend that you keep them separate.
You can do it in migration itself, create a migration file with blank=True, null=True in subject field.
class Apple(models.Model):
text = models.TextField()
subject = models.CharField(max_length=128, blank=True, null=True)
Then create another empty migration file.
python manage.py makemigrations --empty yourappname
Paste below code in that file.
from django.db import migrations
def set_subject(apps, schema_editor):
Apple = apps.get_model('yourappname', 'Apple')
for a in Apple.objects.all():
a.subject = a.text
a.save()
class Migration(migrations.Migration):
dependencies = [
('yourappname', 'name of above migration file'),
]
operations = [
migrations.RunPython(set_subject),
]

IntegrityError using Django's loaddata when switching to Postgres

I am getting the following error:
IntegrityError: duplicate key value violates unique constraint "users_userprofile_pkey"
I am migrating from MySQL to Postgres, so I am dumping the data from the MySQL database using:
python2.7 manage.py dumpdata --indent=4 --natural > dump.json
I get the error when I attempt to load the dump.json into the Postgresql database:
python manage.py loaddata dump.json
I have the following signals in my users/model:
post_save.connect(create_user_profile, sender=User, dispatch_uid="user_create_profile")
post_save.connect(create_api_key, sender=User, dispatch_uid="user_create_api_key")
I had to comment out the post_save signals and then do the loaddata.
the problem may be because of the --natural keyword, if you read the docs about dumpdata natural keys here you will see it has some problems that apply to your database migration.
Also here they talk about a solution to this problem which seems to be pretty interesting (and tedious).
You can always try to add first the models that doesn't depend on each other so you can be sure they exists before trying to create another one. i.e:
if you have this models:
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
birthdate = models.DateField()
class Meta:
unique_together = (('first_name', 'last_name'),)
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Person)
Then migrate the Person class first and then the book class.
Also if you can post the error it would be very helpful (since I could be more specific) but I am pretty certain the problem is a primary key issue

Categories

Resources