With Django 1.11, I am trying to add a new column that is conditioned on other columns (as shown in the below image) and view it at front-end. This link is the closest example but I would like to implement it in Django. How can we do this?
I suggest implement this action on the migration file:
After you changed model, execute ./manage.py makemigrations
Open new migration file in editor, content of this file maybe is similar as below:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [('migrations', '0001_initial')]
operations = [
migrations.AddField('MyModel', 'A_islargerthan_B', models.BooleanField(default=False)),
]
Now you must inject your updater code by using migrations.RunPython :
from django.db import migrations, models
def update_A_islargerthan_B(apps, schema_editor):
MyModel = apps.get_model('my_app', 'MyModel')
for obj in MyModel.objects.all():
obj.A_islargerthan_B = obj.column_A > obj.column_B
obj.save()
class Migration(migrations.Migration):
dependencies = [('migrations', '0001_initial')]
operations = [
migrations.AddField('MyModel', 'A_islargerthan_B', models.BooleanField(default=False)),
migrations.RunPython(update_A_islargerthan_B),
]
Run ./manage.py migrate
Read more about Django migrations
Related
I'm trying to perform a data migration in an app. I would like to add the anonymous user (the django-guardian AnonymousUser) to a public group. Somehow the user does not exist when i'm running test (test database migrations fail with user matching query does not exist). It does work with my development database. Thanks in advance.
As it seems that the anonymous user is created on management init, I tried to import the module in apply_migration without success.
# Generated by Django 4.1 on 2022-10-19 12:11
from django.db import migrations
from guardian.utils import get_anonymous_user
from recipebook.settings import PUBLIC_GROUP_NAME
from django.contrib.auth.models import Group
def apply_migration(apps, schema_editor):
import guardian.management.__init__
public_group = Group.objects.get(
name=PUBLIC_GROUP_NAME
)
user = get_anonymous_user()
user.groups.add(public_group)
def revert_migration(apps, schema_editor):
public_group = Group.objects.get(
name=PUBLIC_GROUP_NAME
)
user = get_anonymous_user()
user.groups.remove(public_group)
class Migration(migrations.Migration):
dependencies = [
('recipebook', '0031_recipenutrition'),
('guardian', '0001_initial'),
]
operations = [
migrations.RunPython(apply_migration, revert_migration)
]
Lead-up:
I subclassed django.db.models.fields.CharField. Then used that custom field called myapp.models.QueryStringField in a model and made my migrations and migrated successfully. Then I changed my mind and decided to replace it with a normal CharField in my model, which I did (again with successfull migration).
Problem:
When I then deleted the QueryStringField class entirely from myapp.models and did makemigrations, it threw the following error (last lines shown here):
File "C:\...\migrations\00....py", line 17, in Migration
field=myapp.models.QueryStringField(max_length=255),
AttributeError: module 'myapp.models' has no attribute 'QueryStringField'
What can I do to fix this? I understand that this is technically correct, since the migration references a class that is not present, but surely this can be solved somehow. I am a little nervous about just deleting migration files.
You can not just delete a field class, that class is referenced by the migration files.
You should change the migration files where the QueryStringField is involved. You can inspect the migration where you changed the field, and remove that part of the migration, so:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('someapp', '1234_some_name'),
]
operations = [
# migrations.AlterField(
# model_name='mymodel',
# name='myfield',
# field=models.QueryStringField(
# # ...
# ),
# ),
]
as well as in the migration where you change it back:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('someapp', '5678_some_other_name'),
]
operations = [
# migrations.AlterField(
# model_name='mymodel',
# name='myfield',
# field=models.CharField(
# # ...
# ),
# ),
]
After you removed these changes (and all changes that thus work with the QueryStringField), you can safely remove it.
I want to generate multiple country objects with the similar language object without going through the admin UI.
models.py
from django.db import models
class World(models.Model):
country = models.CharField(max_length=200)
Language = models.CharField(max_length=200)
class add_countries(models.Model):
sub_part1 = ['USA','ENGLAND','AUSTRALIA','CANADA']
for sub in sub_part1:
sub = World.country
World.Language = "English"
add_countries()
for country in ['USA','ENGLAND','AUSTRALIA','CANADA']:
World.objects.get_or_create(country=country, language='English')
You can put above code inside a method and call that.
If you're looking to have a few database entries that are always there, you should probably consider using data migrations. This would result in these database rows being created when you migrate your database. The basic idea would be something like this:
from django.db import migrations
def add_languages(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
World = apps.get_model('yourappname', 'World')
languages = {'English': ['USA','ENGLAND','AUSTRALIA','CANADA']}
for language, countries in languages.items():
for country in countries:
World.objects.get_or_create(country=country, Language=language)
class Migration(migrations.Migration):
dependencies = [
('yourappname', '0001_initial'),
]
operations = [
migrations.RunPython(add_languages),
]
The migration file would be in your app's migrations directory (something like project_root/yourappname/migrations/0002_insert_languages.py in this case). Consult the documentation for more information.
I have a migrations come from the work of another person, and I'm in on a code base controlled by the version too. I created a migration file after adding a new field but the problem is in the data migration (0003_datamigration_initial_service_configuration.py)that is created before through the function get_or_create () is executed in the head of the list while my migration file data in the end I should not change a migration already developed.
This is my list of migrations
0001_initial.py
0002_datamigration_initial_users_list.py
0003_datamigration_initial_mymodel.py
...
0015.addnewfield
0003_datamigration_initial_mymodel.py:
from __future__ import unicode_literals
from django.db import migrations
from ..models import MyModel
def create_initial_mymodel(apps, schema_editor):
current_product_type, created = MyModel.objects.get_or_create()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0002_datamigration_initial_users_list'),
]
operations = [
migrations.RunPython(create_initial_mymodel),
]
Rhe error is no such column named new_field
How can I fix the problem without editing any data migrations?
You should use apps.get_model to get the MyModel model, instead of importing it directly.
def create_initial_mymodel_forward(apps, schema_editor):
MyModel = apps.get_model('myapp', 'MyModel')
current_product_type, created = MyModel.objects.get_or_create()
Using apps.get_model will load a historical version of the model with the correct fields.
I'm trying to create a auth.Group with permissions automaticly with migrations. My problem is that when I run migrate on empty database the migration that tries to attach permission to the group can't find the permission. If I target an earlier migration so that migrate exits without an error the permissions appear into the database and after that the migration code can find the permission. So what can I do so that the migration can reference a permission which is created in an earlier migration when the migrations are run back to back?
def load_data(apps, schema_editor):
Permission = apps.get_model('auth', 'Permission')
Group = apps.get_model('auth', 'Group')
can_add = Permission.objects.get(codename='add_game')
developers = Group.objects.create(name='Developer')
developers.permissions.add(can_add)
developers.save()
class Migration(migrations.Migration):
dependencies = [
('myApp', '0004_game'),
]
operations = [
migrations.RunPython(load_data),
]
The game model is created in an earlier migration. This code causes always an error stating that Permission matching query does not exist when I run it with other migrations on an empty database.
I'm using python 3.4 with django 1.7.2
Oh. 4 years later...
To create permissions Django uses post_migrate signal.
Therefore, when running all migrations at a time, permissions do not yet exist.
Therefore, you can take out your function, for example, in the management command.
However, you can still do it like this:
from django.contrib.auth.management import create_permissions
APPS = [
...your app labels
]
def create_applications_permissions():
for app in APPS:
app_config = django_apps.get_app_config(app)
create_permissions(app_config)
def load_data(apps, schema_editor):
create_applications_permissions()
Permission = apps.get_model('auth', 'Permission')
Group = apps.get_model('auth', 'Group')
can_add = Permission.objects.get(codename='add_game')
developers = Group.objects.create(name='Developer')
developers.permissions.add(can_add)
developers.save()
class Migration(migrations.Migration):
dependencies = [
('myApp', '0004_game'),
]
operations = [
migrations.RunPython(load_data),
]
And to create permissions do not use apps passed to the migration. Will not pass the check in create_permissions:
if not app_config.models_module:
return
But you have to be careful.
I hope someone will be useful.