Make Migrations on Django - python

I have a Django model which looks like this
class RedUsers(BaseModel):
user_email = models.EmailField(null=True, blank=True)
user_name = models.CharField(max_length=30, null=True, blank=True)
red_id = models.CharField(max_length=30, null=True, blank=True)
active = models.BooleanField(default=False)
def __str__(self):
return self.user_email
class Meta:
verbose_name_plural = "Red Users"
I want to add a new field
activation_key = models.CharField(max_length=40, null=True, blank=True)
I already have lots of data in this model and I can't drop the table, so I need to make migration manually.
I have tried adding the model from my 0001_initial.py file without luck
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name='RedUsers',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('user_email', models.EmailField(blank=True, max_length=254, null=True)),
('user_name', models.CharField(blank=True, max_length=30, null=True)),
('red_id', models.CharField(blank=True, max_length=30, null=True)),
('active', models.BooleanField(default=False)),
],
options={
'verbose_name_plural': 'RED Users',
},
),
migrations.AddField(
model_name='redusers',
name='activation_key',
field=models.CharField(blank=True, max_length=40, null=True, verbose_name='activation key'),
),
]
When I run
python manage.py migrate
It says Your models have changes that are not yet reflected in a migration, and so won't be applied.
I don't know what else to do

I want to add a new field
activation_key = models.CharField(max_length=40, null=True, blank=True)
I already have lots of data in this model and I can't drop the table,
so I need to make migration manually.
You don't need to. If you run makemigrations a second time, Django will detect that you added a field, and will make an extra migration file to add that field to the model.
You thus better here remove the AddField migration object from the migration file, and run python3 manage.py makemigrations.
It will make a new file, likely something that starts with 0002_….py, and it will take the first migration as dependency.
You can then run python3 manage.py migrate, and Django will add the field at the database level, and insert the name of the migration in the migration table.

Related

Why am I unable to migrate when other files use my models in Heroku?

For context, I have an application that works perfectly fine locally, after some fiddling with the database. It uses a react frontend, with a django backend for internal api calls. However, on a new, fresh download, with a new, fresh database, I always get an error saying relation "claims" does not exist, where Claims is the name of a table in my database, in the form of a model.
I have been able to bypass this error by commenting out all code that uses the model, then slowly migrating every single table, one at a time, then uncommenting out the code that uses the model.
This is incredibly tedious, but it works in a local environment. However, as I attempt to push this into production, I am using Heroku, and I am unable to make multiple commits in the same way, as it seems the database gets reset everytime there is a new update.
Am I missing something? I feel as though there must be something I am doing incorrectly here, but I have not been able to find anything other than posts saying to reset all my migrations, and redoing the makemigrations command. This method hasn't worked for me in Heroku, because I need to do each migration individually, as I said before.
For reference, here are my related files:
models.py
class Claims(models.Model):
id = models.BigAutoField(primary_key=True)
refId = models.CharField(db_column='refId', unique=True, max_length=10) # Field name made lowercase.
title = models.CharField(max_length=20, blank=True, null=True)
description = models.CharField(max_length=256, blank=True, null=True)
image = models.CharField(max_length=70, blank=True, null=True)
created_at = models.DateTimeField(blank=True, null=True)
start = models.DateTimeField(blank=True, null=True)
end = models.DateTimeField(blank=True, null=True)
distributor = models.CharField(max_length=20, blank=True, null=True)
status = models.TextField(blank=True, null=True, choices=claimStatus.choices, default=claimStatus.active) # This field type is a guess.
class Meta:
managed = True
db_table = 'claims'
unique_together = (('id', 'refId'),)
migrations/0001_initial.py
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Claims',
fields=[
('id', models.BigAutoField(primary_key=True, serialize=False)),
('refId', models.CharField(db_column='refId', max_length=10, unique=True)),
('title', models.CharField(blank=True, max_length=20, null=True)),
('description', models.CharField(blank=True, max_length=256, null=True)),
('image', models.CharField(blank=True, max_length=70, null=True)),
('created_at', models.DateTimeField(blank=True, null=True)),
('start', models.DateTimeField(blank=True, null=True)),
('end', models.DateTimeField(blank=True, null=True)),
('distributor', models.CharField(blank=True, max_length=20, null=True)),
('status', models.TextField(blank=True, choices=[('ACTIVE', 'Active'), ('INACTIVE', 'Inactive'), ('DISCONTINUED', 'Discontinued')], default='ACTIVE', null=True)),
],
options={
'db_table': 'claims',
'managed': True,
'unique_together': {('id', 'refId')},
},
),
]
useClaim.py
from .models import *
claim, created = Claims.objects.get_or_create(
refId = "DROPTEST",
title = "DROPTEST",
description ="DROPTEST",
image = "https://ipfs.io/ipfs/QmcPjQ7iaZ8exuZnH1awHZtkQPyL3TRT1S46wVJxwucay5",
created_at = None,
start = None,
end = None,
distributor = "DROPTEST",
status = claimStatus.active
)
claim.save()
Thanks to #AbdulAzizBarkat, I found that the issue was not in the compilation level of the application as I had originally thought. I had code modifying/referencing the models before they were migrated. I tried the ready method of AppConfig, however that did not work for me. Instead, I took the database initialization and wrote a migration operation instead, and that worked wonderfully.

Modify model generated by django-activity-stream

I am creating a project which needs an audit in the database about all kind of actions performed by the user. For this objective, I m using 'Django-activity-stream' which creates its model properly.
I want to change the type of one parameter in the model generated by this library but I m not sure how to do it.
PD: This is my first time with Django and has seen the documentation of both but I'm not really sure.
If I explained something wrong or you need more info about it ask me without any problem.
EDIT1:
Lib 'Django-activity-stream' create the next migration by model 'Action'
migrations.CreateModel(
name='Action',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, help_text='', auto_created=True)),
('actor_object_id', models.CharField(max_length=255, db_index=True, help_text='')),
('verb', models.CharField(max_length=255, db_index=True, help_text='')),
('description', models.TextField(blank=True, null=True, help_text='')),
('target_object_id', models.CharField(max_length=255, blank=True, null=True, db_index=True, help_text='')),
('action_object_object_id', models.CharField(max_length=255, blank=True, null=True, db_index=True, help_text='')),
('timestamp', models.DateTimeField(db_index=True, default=django.utils.timezone.now, help_text='')),
('public', models.BooleanField(db_index=True, default=True, help_text='')),
('data', DataField(blank=True, null=True, help_text='')),
('action_object_content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, blank=True, null=True, help_text='', related_name='action_object', to='contenttypes.ContentType')),
('actor_content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, help_text='', related_name='actor', to='contenttypes.ContentType')),
('target_content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, blank=True, null=True, help_text='', related_name='target', to='contenttypes.ContentType')),
],
options={
'ordering': ('-timestamp',),
},
),
I only want to change the parameter 'verb' from models.CharField to models.ForeignKey and associated it to with a model I defined previously.
Finally, to solve this problem i made the next steps:
Fork of 'Django-activity-stream'
Modified the model and adapt its functions to this change
Upload it like my own library in Pypi with reference to the original author.
This has been my decision because the documentation and another questions about this topic said that Django doesnt allow to do it. Then the unique method viable is fork and modify it.

Django Renaming/Refactoring a Custom User Model

I have a custom user model: class CustomUser(AbstractUser): already migrated and populated with some records. I want to rename this CustomUser to MyUserModel. In Pycharm I right-clicked on the name and chose refactor - rename so every reference to this model is also renamed.
I then ran python3 manage.py makemigrations which gave me the below error:
"AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
So I went to myproject.settings and changed the AUTH_USER_MODEL to MyUserModel.
AUTH_USER_MODEL = 'users.MyUserModel'
The makemigrations then worked. and when I looked into the migration file it looked like this:
class Migration(migrations.Migration):
dependencies = [
('auth', '0011_update_proxy_permissions'),
('users', '0002_auto_20190916_0658'),
]
operations = [
migrations.CreateModel(
name='MyUserModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.DeleteModel(
name='CustomUser',
),
]
I guess migration manager did not detect the rename but is creating the new table. Which I do not mind since I dont have important data yet.
when I then run python3 manage.py migrate the below error occurs:
ValueError: The field account.EmailAddress.user was declared with a lazy reference to 'users.myusermodel', but app 'users' doesn't provide model 'myusermodel'.
The field admin.LogEntry.user was declared with a lazy reference to 'users.myusermodel', but app 'users' doesn't provide model 'myusermodel'.
The field authtoken.Token.user was declared with a lazy reference to 'users.myusermodel', but app 'users' doesn't provide model 'myusermodel'.
The field socialaccount.SocialAccount.user was declared with a lazy reference to 'users.myusermodel', but app 'users' doesn't provide model 'myusermodel'.
Why is this happening? I also tried a migration with RenameModel rather than creating a new table and deleting the old one. Still got the same error.

one of my few django migrations does not run [duplicate]

This question already has answers here:
Rerun a Django data migration
(3 answers)
Closed 5 years ago.
I have a django migration:
0020_delete_cesiumentity
which deletes a table...
then I rebuild it (this is was trying to fix a previous problem I had) with this migration I created:
0021_cesiumentity.py
# -*- coding: utf-8 -*-
# Generated by Django 1.9.5 on 2016-12-19 22:45
from __future__ import unicode_literals
import django.contrib.gis.db.models.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('swsite', '0020_delete_cesiumentity'),
]
operations = [
migrations.CreateModel(
name='CesiumEntity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('be_number', models.CharField(max_length=100)),
('image_id', models.CharField(blank=True, max_length=100, null=True)),
('mission_id', models.CharField(blank=True, max_length=100, null=True)),
('product_type', models.CharField(blank=True, max_length=100, null=True)),
('polarization', models.CharField(blank=True, max_length=256, null=True)),
('mode_id', models.CharField(blank=True, max_length=100, null=True)),
('mode_name', models.CharField(blank=True, max_length=100, null=True)),
('acquisition_type', models.CharField(blank=True, max_length=100, null=True)),
('image_size_samples', models.CharField(blank=True, max_length=100, null=True)),
('image_size_lines', models.CharField(blank=True, max_length=100, null=True)),
('sample_spacing_range', models.CharField(blank=True, max_length=100, null=True)),
('line_spacing_azimuth', models.CharField(blank=True, max_length=100, null=True)),
('pass_direction', models.CharField(blank=True, max_length=100, null=True)),
('look_direction', models.CharField(blank=True, max_length=100, null=True)),
('grazing_angle', models.CharField(blank=True, max_length=100, null=True)),
('azimuth_angle', models.CharField(blank=True, max_length=100, null=True)),
('doppler_cone_angle', models.CharField(blank=True, max_length=100, null=True)),
('file_format', models.CharField(blank=True, max_length=100, null=True)),
('name', models.CharField(max_length=100)),
('file_name', models.CharField(max_length=256)),
('country_code', models.CharField(blank=True, max_length=64, null=True)),
('collection_date', models.DateField(blank=True, null=True)),
('collection_start_time', models.CharField(blank=True, max_length=256, null=True)),
('corner_coords', models.CharField(max_length=255)),
('sensor', models.CharField(max_length=128)),
('target_name', models.CharField(blank=True, max_length=256, null=True)),
('file_size', models.IntegerField()),
('dzi_location', models.CharField(max_length=256)),
('kml_location', models.CharField(max_length=256)),
('kmz_location', models.CharField(max_length=256)),
('thumbnail_location', models.CharField(max_length=256)),
('resource_location', models.CharField(max_length=256)),
('processed', models.BooleanField(default=False)),
('created_at', models.DateField(auto_now_add=True)),
('updated_at', models.DateField(auto_now=True)),
('mpoly', django.contrib.gis.db.models.fields.PolygonField(srid=4326)),
],
),
]
This migration does not run, causing my 0022 migration to fail since the table is not put back. I am not sure why this does not run or if I need to do something more. I tried to force it with a:
python manage.py migrate swsite 0021_cesiumentity
and I just get this:
Operations to perform:
Target specific migration: 0021_cesiumentity, from swsite
Running migrations:
No migrations to apply.
So I am not sure why this is happening or what I am missing?
I had issues with previous migrations saying things existed (which makes sense I am not working on my development but my test server), so I just faked those if that matters I am not sure.
Perhaps you made a mistake when faking migrations.
What does python manage.py showmigrations output? If it shows 0021_cesiumentity as being applied, then running python manage.py migrate swsite 0021_cesiumentity will have no effect.
To re-run that migration, you would have to fake back to the migration before (0020), then rerun python manage.py migrate swsite 0021_cesiumentity.
Django migrations are tracked using the 'django_migrations' table in your database. This is how Django records what migrations have been applied and what hasn't. If you check in this table, it will show you the migration file names that have been run on the DB.
If you want to rerun a migration, you need to delete the row in the django_migrations table with the corresponding file name. Then migrate again.

Django: cannot add foreight key to User

I am using ldap to do authentication, just like Understanding Django-LDAP authentication.
My model is:
class MyFile(models.Model):
file = models.FileField(upload_to="files")
slug = models.SlugField(max_length=50, blank=True)
user = models.ForeignKey(User, unique=True)
But I cannot make migrations:
python src/manage.py makemigrations
You are trying to add a non-nullable field 'user' to myfile without a default;
we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
Select an option:
Then I input datetime.date.today() and run python manage.py migrate
The error is:
File "/usr/local/lib/python2.7/dist-packages/django/db/models/fields/__init__.py", line 915, in get_prep_value
return int(value)
TypeError: int() argument must be a string or a number, not 'datetime.date'
Any idea? Thanks
UPDATE
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='MyFile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('file', models.FileField(upload_to='files')),
('slug', models.SlugField(blank=True)),
('user', models.ForeignKey(User, blank=True, null=True)),
],
),
]
Error:
ValueError: Lookup failed for model referenced by field fileupload.MyFile.user: auth.User
You need to provide a default User ID for all the existing files. It has to be an existing User ID and an integer. It cannot be a datetime.date.
Or, if applicable, you can make the File->User link optional:
user = models.ForeignKey(User, blank=True, null=True)

Categories