Django AbstractEmailUser model column does not exist - python

I created a CustomUser model, inheriting from AbstractEmailUser.
I wanted to add an avatar field, after finishing it and making migrations but I'm getting the following error:
column account_customuser.avatar does not exist
LINE 1: ...user"."name", "account_customuser"."valid_email", "account_c...
models.py looks like this now
class CustomUser(AbstractEmailUser):
nickname = models.CharField('nickname', max_length=100, unique=True)
name = models.CharField(max_length=200, blank=True, null=True, default=None)
valid_email = models.BooleanField('valid email', default=False, blank=True)
avatar = models.ImageField(upload_to='profile/photo', blank=True, null=True, default=None)
What can I do to correctly add the avatar field?

As stated here: Django Programming error column does not exist even after running migrations
Something may have gone wrong in your migration process.
Go to your database and find a table named django_migrations where
all the migrations are listed.
Find the row with the migration in which you added the avatar column to your model and delete it from the database (only the row).
Migrate again: ./manage.py migrate
Another possibility is that you are using Django Toolbar like what happened here: Django Migration Error: Column does not exist, in which case you need to comment the toolbar in your installed apps and rerun migrations.

Did you apply a new migration with these changes?
You can check this using showmigrations or use makemigrations to create a migration and migrate to apply it.

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 create a new column in an already existing table

I'm using Django 3.0.5 and I am trying to create a new column in a table.
The table looks like this:
class VacationModel(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
emp_id = models.IntegerField()
email = models.EmailField()
from_date = models.DateField()
to_date = models.DateField()
reason = models.TextField()
time_sent = models.DateTimeField("date sent")
req_approved = models.BooleanField(default=False, null=True)
req_denied = models.BooleanField(default=False, null=True)
# daysoff_given = models.IntegerField()
def __str__(self):
return self.emp_id
The new column would be daysoff_given. I tried adding this column and after running python manage.py makemigrations I got an error saying django.db.utils.OperationalError: no such column
I tried following some other answers and I deleted the migrations made inside the migrations folder, without deleting the __init__.py file. After running makemigrations again the same error occured and then I deleted the whole model and made a new model.
I think my database is broken, but is there an actual way to avoid this, since it has already happened two times.
Whenever I try to add a new column, it always throws that error and I cannot continue. How can I fix this?
I think the problem is that you created migrations but didn't apply them. Make sure you run both of the following commands after adding the column in the Model.
python manage.py makemigrations
python manage.py migrate
It it doesn't work, please edit your question and add the full trackback error to help us know what is the causing the error.

Adding db_table to model added a last_login field

Background: I started a project with a custom User model. However, noob that I am, I was unaware of the AbstractBaseUser class. So I just wrote my own. The app has been deployed to prod and working fine. But now I want to switch to using AbstractBaseUser so I can take advantage of some of the built-in Django utilities (like the pre-made password resetting process). I had done this with a different app and it worked fine. But that one wasn't in prod while I made the change. Because this one is, I needed to keep the old user table while I made the changes with a copy of it. So my first step was to add db_table = test_users to my old user model, so as to keep the prod app running with an unchanged table. I ran the migration, and two unexpected things happened (I'm a noob, and that's why they were unexpected):
The old user table was renamed. I thought a new table would be created. No problem, I quickly copied the new table and named the copy with the old table's name so the prod app could still find its users
A column last_login was added. Why??
Here's my model, with the added db_table
class User(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.CharField(max_length=255)
password = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
client_id = models.IntegerField(blank=True, null=True)
is_admin = models.BooleanField(default=False)
is_super = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
class Meta:
db_table = "test_users"
The big problem with this is that when I change to AbstractBaseUser and run the migration, I get an error. Looking at the migration file I see that this change creates a migration that all it tries to do is to add last_login to the table. So, of course, the error I get is "Duplicate column name 'last_login'"
So, my question is two-fold:
Why was that column added in the first migration?
If I just run migrate --fake and keep going, will it have unintended consequences? I thought this could be a good solution, given that the migration file shows nothing else is being done, and if the field already exists, then no harm done?
Maybe because you've changed the parent class django automatically change all the migrations that connected to your user class

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),
]

How do I specify slugifying code in this South migration?

I have a model like:
class Thing(models.Model):
title = models.CharField(_('Title'), max_length=255)
I want to add this NOT NULL field:
slug = models.SlugField(_('Slug'), max_length=255)
When I run "python manage.py schemamigration things --auto", I get prompted to enter Python code for my one-off default value.
What should I enter here in order to lowercase and slugify the existing titles? And is there anything else that I have to do with the migration, before running 'migrate'?
i'd probably leave it blank in the migration, and instead follow it with a data migration creating the slugs there with some code

Categories

Resources