Django migrate error name 'bPath' is not defined - django

I'm running on Django 1.7.4.
# base.py
PRIVATE_FOLDER_ROOT = str(PROJECT_DIR.child('web_private'))
# tested: PRIVATE_FOLDER_ROOT = PROJECT_DIR.child('web_private')
# tested: PRIVATE_FOLDER_ROOT = '/var/www/project/project/web_private'
# models.py
from django.conf import settings
#python_2_unicode_compatible
class MessageFile(models.Model):
"""
"""
fs_private_folder = FileSystemStorage(location=settings.PRIVATE_FOLDER_ROOT)
message = models.ForeignKey(Message)
file = models.FileField('file', storage=fs_private_folder, upload_to=get_upload_path_message_file)
when I run
./manage.py migrate <my_app> --settings=myapp.settings.local
I get the following error
NameError: name 'bPath' is not defined
Checking the 0001_initial.py I see that bPath is not imported or defined.
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('file', models.FileField(upload_to=apps.admin_messages.models.get_upload_path_message_file, storage=django.core.files.storage.FileSystemStorage(location=bPath('/var/www/project/project/web_private')), verbose_name=b'file')),
('message', models.ForeignKey(to='admin_messages.Message')),
],
This SO question is linked to mine, but the proposed solution doesn't work.
Thanks,
D

It looks like makemigrations automatically adds a "b" in front of string literals to mark them as byte strings in Python 3.
It may help if you change the cast from str to unicode, ie:
PRIVATE_FOLDER_ROOT = unicode(PROJECT_DIR.child('web_private'))

Related

How to set default value for a model field based on enum in Django?

I'm using Django 2.2.5 and have multiple choice fields based on enums in my models. For an unknown reason I now get a migration error when using an enum for choice field during migration:
django.db.utils.OperationalError: (1067, "Invalid default value for 'protocol'")
model.py
from django.db import models
# See class above
from .utils import NetworkProtocolList
class Networks(models.Model):
ipv4 = models.GenericIPAddressField(blank=False, null=False)
protocol = models.CharField(choices=NetworkProtocolList.choices(), max_length=20,default=NetworkProtocolList.ETH)
class Meta:
managed = True
db_table = 'networks'
utils.py
from enum import Enum
class NetworkProtocolList(Enum):
ETH = 'Ethernet'
MPLS = 'MPLS'
#classmethod
def choices(cls):
return [(key.name, key.value) for key in cls]
I issued
manage.py makemigrations
and subsequent
manage.py migrate
generated the following error:
django.db.utils.OperationalError: (1067, "Invalid default value for
'protocol'")
xxxx_auto_xxxxxxxx_xxxx.py
# Auto generated migration file
import my_.utils
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('my_app', 'yyyy_auto_yyyyyyyy_yyyy'),
]
operations = [
migrations.AddField(
model_name='networks',
name='protocol',
# Field definition here, pay attention to the default value
field=models.CharField(choices=[('ETH', 'Ethernet'), ('MPLS', 'MPLS')], default=my_app.utils.NetworkProtocolList('Ethernet'), max_length=20),
),
]
Than I edited migration file to manually set the default to a string instead of calling enum class:
xxxx_auto_xxxxxxxx_xxxx.py
# Edited migration file
import my_.utils
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('my_app', 'yyyy_auto_yyyyyyyy_yyyy'),
]
operations = [
migrations.AddField(
model_name='networks',
name='protocol',
# Field definition here, pay attention to the modified default value
field=models.CharField(choices=[('ETH', 'Ethernet'), ('MPLS', 'MPLS')], default='Ethernet', max_length=20),
),
]
Now migration works properly but I wonder why I can't define default value like before using the enum instead of a litteral string, because I have other model field for whom this has worked properly.
Is that a bug, what am I lissing here, How to set default value for a model field based on enum in Django?
Since you are using Django<3.X, Django isn't able to identify the enum value. So, use the .value property of enum class as
protocol = models.CharField(
choices=NetworkProtocolList.choices(),
max_length=20,
default=NetworkProtocolList.ETH.value # &lt--- change is here
)

how to add another 0000n_initial.py file from makemigrations command

i want to add another initial.py file from makemigrations file
when i try to py manage.py makemigrations it show error
you are trying to add a non-nullable field 'role' to user without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix :
Provide a one-off default now(will be set on all existing rows with a null value for this column)
Quit, and let me add a default in models.py
i want to make another init to make a dependent dropdown
this is what i write in models.py
import datetime
from django.db import models
from django.utils import timezone
class TableAll(models.Model):
table_name = models.CharField(max_length=250)
and this is the code that 0001_initial.py has
# Generated by Django 2.2.2 on 2019-10-29 03:52
from django.db import migrations, models
from django.contrib.auth.models import User
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
role = models.CharField(max_length=250)
role.contribute_to_class(User,'role')
operations = [
migrations.CreateModel(
name='TableAll',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('table_name', models.CharField(max_length=250)),
],
),
]
i want to add a foreign key to another model and want to makemigrations to add a new 00002_initial.py(for example) and i want to have something like this(here is the code i found from github source)
new initial file (0002_add_initial_data.py) //this is just an example from github source code where it has 0001_initial.py and 0002_add_initial_data.py to make the dependent dropdown works
class Migration(migrations.Migration):
Country = apps.get_model('hr', 'Country')
City = apps.get_model('hr', 'City')
india = Country.objects.create(name='India')
City.objects.create(name='Bengaluru', country=india)
City.objects.create(name='Mumbai', country=india)
City.objects.create(name='Chennai', country=india)
City.objects.create(name='Hyderabad', country=india)
City.objects.create(name='New Delhi', country=india)
usa = Country.objects.create(name='United States')
City.objects.create(name='New York', country=usa)
City.objects.create(name='San Francisco', country=usa)
City.objects.create(name='Los Angeles', country=usa)
City.objects.create(name='Chicago', country=usa)
City.objects.create(name='Seattle', country=usa)
russia = Country.objects.create(name='Russia')
City.objects.create(name='Moscow', country=russia)
City.objects.create(name='Saint Petersburg', country=russia)
City.objects.create(name='Yekaterinburg', country=russia)
City.objects.create(name='Kazan', country=russia)
City.objects.create(name='Krasnodar', country=russia)
brazil = Country.objects.create(name='Brazil')
City.objects.create(name='Sao Paulo', country=brazil)
City.objects.create(name='Rio de Janeiro', country=brazil)
City.objects.create(name='Belo Horizonte', country=brazil)
City.objects.create(name='Curitiba', country=brazil)
City.objects.create(name='Recife', country=brazil)
uk = Country.objects.create(name='United Kingdom')
City.objects.create(name='London', country=uk)
City.objects.create(name='Huddersfield', country=uk)
City.objects.create(name='Glasgow', country=uk)
City.objects.create(name='Edinburgh', country=uk)
City.objects.create(name='Cambridge', country=uk)
dependencies = [
('hr', '0001_initial'),
]
operations = [
migrations.RunPython(add_initial_data),
]
Thankyou for the help, im new to this django framework , and i need to use it for my thesis ..
There is a pattern that can be followed when a non-nullable field is being added to a model and the value of that field is the result of a script.
Add the field to your model but make it nullable (null=True)
Run makemigrations to create a migration that adds the nullable field
Create another migration (makemigrations --empty) that fills in this column using migrations.RunPython
Remove null=True from the field and run makemigrations again. When prompted with the selection choose 1 "Provide a one-off default now" and enter any integer you like as all rows should already have a value it will not matter
migrate

django.db.utils.NotSupportedError in sqlite why not supported in sqlite

class M_Post(models.Model):
''''
CODE
''''
class M_File(models.Model):
....
CODE
....
class M_Post_File(models.Model):
post = models.ForeignKey(M_Post,on_delete=models.CASCADE)
file = models.ForeignKey(M_File,on_delete=models.CASCADE,null=True)
error:
django.db.utils.NotSupportedError: Renaming the 'posts_file' table while in a transaction is not supported on SQLite because it would break referential integrity. Try adding atomic = False to the Migration class.
how to solve this error
Go to related migration file(automatically created in migrations directory after makemigrations command) and add atomic = False to the Migration class. Migration(migrations.Migration):. Then you can migrate the changes.
example code:
# Generated by Django 2.1.14 on 2019-12-02 07:07
from django.db import migrations, models
class Migration(migrations.Migration):
atomic = False # **<<< HERE**
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ebayLog',
fields=[
If you still have the problem here is a example:
# Generated by Django 2.1 on 2018-08-16 21:22
from django.db import migrations
class Migration(migrations.Migration):
atomic = False # <<<< THIS LINE
dependencies = [
('shop', '0004_product_imgfeat'),
]
operations = [
migrations.RenameModel(
old_name='Category',
new_name='CategoryShop',
),
]
I migrated many times after I got this error.
Then I did what Selim said above and I also added atomic = False after class Migration(migrations.Migration): in every migration file, which was a little silly because I didn't know which file was THE related migration file...
Then I searched the "atomic=False" in Django documentation and I found these:1
2
As the error "Renaming the 'posts_file' table while in a transaction is not supported on SQLite" described we know that renaming while in a transaction is not supported on SQLite, so adding atomic=False is needed. But I don't know about DDL transactions so that's too much for me...
If you don't want to touch anything and you've just started your project (well not necessarily), you can just delete the migration files inside the migrations directory and migrate again.
Otherwise, change the atomic variable in the migrations file to False then you can migrate your changes.
Another way, if atomic=false method didn't work, is you can delete generated files in the migration folder and start again by make migrations and migrate
Iam also getting the same error at categories_coupon model.
Go to app which contains categories_coupon model.
Rename the error raising model. (i renamed the 'coupon' model to 'coupons')
open the migrations folder.
and add 'atomic=False' line to all migrations files whose names related to post_file.
then run makemigrations command.
then run migrate command.
then runserver.
For reference look at my models
0003_coupons.py
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
atomic = False #this is the line i added.
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('categories', '0002_auto_20211008_1305'),
]
operations = [
migrations.CreateModel(
name='Coupons',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(blank=True, max_length=200, null=True)),
('code', models.CharField(blank=True, max_length=200, null=True)),
('description', models.TextField()),
('coupon_type', models.IntegerField(choices=[('%', '%'), ('RS', 'RS')])),
('discount', models.DecimalField(decimal_places=2, default=0, max_digits=20)),
('max_users', models.IntegerField(default=0)),
('used_count', models.IntegerField(default=0)),
('startd_date', models.DateField()),
('end_date', models.DateField()),
('icon', models.FileField(upload_to='uploads/banners')),
('is_active', models.IntegerField(choices=[(1, 'Active'), (2, 'Inactive'), (3, 'Deleted')])),
('created_date', models.DateTimeField(auto_now_add=True)),
('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
],
),
]
0004_rename_coupons_coupon.py
-----------------------------------
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
atomic=False #here is the line i added.
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('categories', '0003_coupons'),
]
operations = [
migrations.RenameModel(
old_name='Coupons',
new_name='Coupon',
),
]

Django ProgrammingError column does not exist

I've recently migrated to postgresql, I was not sure about the cause of the problem but column does not exist error is showing up.
ProgrammingError at /admin/mtsauth/authorms/
column mtsauth_authorms.nihgrants does not exist
LINE 1: ..."secfirstname", "mtsauth_authorms"."seclastname", "mtsauth_a...
this is migrations file
migrations.CreateModel(
name='AuthorMS',
fields=[
('firstname', models.CharField(max_length=120)),
('lastname', models.CharField(max_length=120)),
('ArticleId', models.AutoField(primary_key=True, `enter code here`serialize=False)),
('secfirstname', models.CharField(blank=True, default='None', max_length=120)),
('seclastname', models.CharField(blank=True, default='None', max_length=120)),
('nihgrants', models.BooleanField(default=False)),
('country', models.CharField(choices=[('INDIA', 'INDIA'), ('US', 'USA'), ('UK', 'UK'), ('RUSSIA', 'RUSSIA')], max_length=50)),
('seccountry', models.CharField(blank=True, choices=[('INDIA', 'INDIA'), ('US', 'USA'), ('UK', 'UK'), ('RUSSIA', 'RUSSIA')], default='None', max_length=50)),
('affliation', models.CharField(default='None', max_length=100)),
('secAffliation', models.CharField(blank=True, default='None', max_length=100)),
('code', models.IntegerField(default=101, max_length=10000)),
],
),
Your changes are not fully reflected in the database. This could be because you have not migrated to the database. Be sure you provide value for non-nullable fields to your model by giving them a default value. You can check the status of a migration by running the following command:
python manage.py showmigrations <your_app_name>
This will show the list of migrations. The one without the X to the left of migration is the one you have missed to migrate.
Comment all your urls.py lines. Including all imports. Except:
from django.contrib import admin
from django.urls import path
admin = [
path('admin/', admin.site.urls),
]
In terminal run
python manage.py makemigrations
python manage.py migrate
Solved.

Pass South random unique default values when migrating

I am trying to forward migrate a model with existing data. The model has a new field with constraints unique=True and null=False.
When I do
./manage.py schemamigration myapp --auto
South lets me specify a default value for the new field by asking:
Specify a one-off value to use for existing columns now
Usually I set this to None but since this field needs to be unique I was wondering if it is possible to pass South a unique value via:
>>> import uuid; uuid.uuid1().hex[0:35]
This gives me an error message
! Invalid input: invalid syntax
Any ideas if it is possible to pass South random unique default values when migrating via the commandline?
Thanks.
Unfortunately only the datetime module is available for use as a one-off value in a schemamigration.
However, you can achieve the same effect by splitting this up into three migrations:
add new field to the model without constraints (with null=True, unique=False)
use a datamigration to add the UUID to the new field
add the constraint on the new field (with null=False, unique=True)
Tutorial on data migrations: http://south.readthedocs.org/en/0.7.6/tutorial/part3.html#data-migrations
In django 1.7+ you can do the following. It first adds the field with no indexing and no unique. It then assigns the unique values (I based them on the name and used slugify method which you need to create) and finally alters the field again to add index and unique attributes.
from django.db import migrations
import re
import django.contrib.postgres.fields
from common.utils import slugify
import django.core.validators
def set_slugs(apps, schema_editor):
categories = apps.get_model("myapp", "Category").objects.all()
for category in categories:
category.slug = slugify(category.name)
category.save()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0034_auto_20150906_1936'),
]
operations = [
migrations.AddField(
model_name='category',
name='slug',
field=models.CharField(max_length=30, validators=[django.core.validators.MinLengthValidator(2), django.core.validators.RegexValidator(re.compile('^[0-9a-z-]+$'), 'Enter a valid slug.', 'invalid')], help_text='Required. 2 to 30 characters and can only contain a-z, 0-9, and the dash (-)', unique=False, db_index=False, null=True),
preserve_default=False,
),
migrations.RunPython(set_slugs),
migrations.AlterField(
model_name='category',
name='slug',
field=models.CharField(help_text='Required. 2 to 30 characters and can only contain a-z, 0-9, and the dash (-)', unique=True, max_length=30, db_index=True, validators=[django.core.validators.MinLengthValidator(2), django.core.validators.RegexValidator(re.compile('^[0-9a-z-]+$'), 'Enter a valid slug.', 'invalid')]),
),
]
Here is the Django's official how-to on migrating unique fields.
Migrations that add unique fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Applying a "plain" migration that adds a unique non-nullable field to a table
with existing rows will raise an error because the value used to populate
existing rows is generated only once, thus breaking the unique constraint.
Therefore, the following steps should be taken. In this example, we'll add a
non-nullable :class:`~django.db.models.UUIDField` with a default value. Modify
the respective field according to your needs.
* Add the field on your model with ``default=...`` and ``unique=True``
arguments. In the example, we use ``uuid.uuid4`` for the default.
* Run the :djadmin:`makemigrations` command.
* Edit the created migration file.
The generated migration class should look similar to this::
class Migration(migrations.Migration):
dependencies = [
('myapp', '0003_auto_20150129_1705'),
]
operations = [
migrations.AddField(
model_name='mymodel',
name='uuid',
field=models.UUIDField(max_length=32, unique=True, default=uuid.uuid4),
),
]
You will need to make three changes:
* Add a second :class:`~django.db.migrations.operations.AddField` operation
copied from the generated one and change it to
:class:`~django.db.migrations.operations.AlterField`.
* On the first operation (``AddField``), change ``unique=True`` to
``null=True`` -- this will create the intermediary null field.
* Between the two operations, add a
:class:`~django.db.migrations.operations.RunPython` or
:class:`~django.db.migrations.operations.RunSQL` operation to generate a
unique value (UUID in the example) for each existing row.
The resulting migration should look similar to this::
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
def gen_uuid(apps, schema_editor):
MyModel = apps.get_model('myapp', 'MyModel')
for row in MyModel.objects.all():
row.uuid = uuid.uuid4()
row.save()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0003_auto_20150129_1705'),
]
operations = [
migrations.AddField(
model_name='mymodel',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, null=True),
),
# omit reverse_code=... if you don't want the migration to be reversible.
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
migrations.AlterField(
model_name='mymodel',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, unique=True),
),
]
* Now you can apply the migration as usual with the :djadmin:`migrate` command.
Note there is a race condition if you allow objects to be created while this
migration is running. Objects created after the ``AddField`` and before
``RunPython`` will have their original ``uuid``’s overwritten.
You can manually edit your migration file:
I needed to add random character to some field so I have imported random and randint
import random
import string
and changed the value of default to
default=random.choice(string.lowercase)
It worked.
There is way to do unique value for each row with South.
Define slug in models.py as:
class Foo(models.Model):
slug = models.SlugField(unique=True, default='')
....
Create new migration
run python manage.py schemamigration --auto foo
Open new migration file, and edit it:
# Change add_column to this:
db.add_column(u'account_funnel', 'slug',
self.gf('django.db.models.foo.Foo')(default='',
unique=False,
max_length=50),
keep_default=False)
# right above this add such python code:
foos = orm['foo.Foo'].objects.all()
for foo in foos:
foo.slug = slugify(funnel.name)
foo.save()
# Modify slug as unique field
db.create_unique(u'foo_foo', ['slug'])
ps mark this migration as no_dry_run = True
pss do not forget to import slugify function from django.template.defaultfilters import slugify