How to run migrations on specific database using call_command() in Django? - django

I'm just wondering what the correct syntax is for calling $ python manage.py migrate app_name --database db_name with the management.call_command() function at runtime.
So far, I have the following:
from django.core import management
from django.core.management.commands import migrate
# Migrate the core.contrib.dynamics if needed to the pre-specified database:
management.call_command(migrate.Command(), 'dynamics', '--database {}'.format(DB_NAME))
However, I get the following error at runtime when calling the above:
Cannot find a migration matching '--database default_node' from app 'dynamics'.
I'm 99% sure I'm probably calling the -- args incorrectly? Can anyone point me in the right direction with this?
The migrations for the dynamics app are as follows:
# Generated by Django 3.0.8 on 2020-07-02 14:28
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ModelSchema',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32, unique=True)),
('_modified', models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name='FieldSchema',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=63)),
('data_type', models.CharField(choices=[('character', 'character'), ('text', 'text'), ('integer', 'integer'), ('float', 'float'), ('boolean', 'boolean'), ('date', 'date')], editable=False, max_length=16)),
('null', models.BooleanField(default=False)),
('unique', models.BooleanField(default=False)),
('max_length', models.PositiveIntegerField(null=True)),
('model_schema', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fields', to='dynamics.ModelSchema')),
],
options={
'unique_together': {('name', 'model_schema')},
},
),
]

Considering you already ran the migrations, you can simply use
management.call_command('migrate', app_label='dynamics', database='dbname')

Related

SQL request for a model

models.py
class Country(models.Model):
name = models.CharField(max_length=50, validators=[validate_name, ])
class Meta:
managed = False
db_table = 'countries'
def __str__(self):
return self.name
0001_initial.py
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Country',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50, validators=[countries.validators.validate_name])),
],
options={
'db_table': 'countries',
'managed': False,
},
),
]
sql
(venv) michael#michael:~/Documents/PyCharmProjects/db/db$ python manage.py sqlmigrate countries 0001_initial
BEGIN;
--
-- Create model Country
--
-- (no-op)
COMMIT;
Could you tell me whether this sql reflects the model or not? If not, how can it happen? And will it produce in the database?
There is no sql to apply to the db because of managed = False.
That is, running migrate does not change the db.

Django Postgres makemigrations only Autofield at 0001_initial.py

Python 3.10.4
Django 4.0.5
PostgreSQL 14
When I start "python manage.py makemigrations" i got the file "0001_initial.py" but all Fields, except autofields, are missing.
models.py
from django.db import models
# Create your models here.
class Username(models.Model):
#id = models.AutoField(primary_key=True)
username: models.CharField(max_length=100)
class Carrier(models.Model):
#id = models.AutoField(primary_key=True)
carriername: models.CharField(max_length=100)
desc: models.TextField()
0001_initial.py
# Generated by Django 4.0.5 on 2022-06-29 13:18
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Carrier',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='Username',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
]
First, you must know that Django By default adds the id field to the models ...
Try to Delete the migration file and
you must use the = not the :
so it will be like this
class Username(models.Model):
username=models.CharField(max_length=100)
class Carrier(models.Model):
carriername = models.CharField(max_length=100)
desc = models.TextField()
rerun manage.py makemigrations and it Should work

Premature field validation in Django migrations

I have the following issue:
I work on a Django app that has a primary DB and now we are adding a secondary DB for syncing only some of the data in it. When I tried to run the migrations, I got an error: null value in column 'field_2' violates not-null constraint. And here is the issue:
The model:
class A(models.Model):
field_1 = models.BooleanField(default=False)
field_2 = models.BooleanField(default=True) # added later
field_3 = models.BooleanField(default=True) # added later
and 4 migrations (well, more, but those don't count):
0001 - a related model is created
0002 - model A is created and the relation is created (ForeignKey)
0003 - field_2 is added to model A
0004 - field_3 is added to model A
However when I run migrate on the new DB, the migration stops at migration 0002 with the error mentioned above:
django.db.utils.IntegrityError: null value in column "field_2" violates not-null constraint
even though the field is created in a later migration.
I don't know hot to even begin a workaround this issue.
Edit:
Migration 0001:
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name='B',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('year', models.IntegerField()),
('active', models.BooleanField(default=True)),
],
)
]
Migration 0002:
class Migration(migrations.Migration):
dependencies = ['app', '0001']
operations = [
migrations.CreateModel(
name='A',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('field_1', models.BooleanField(default=False))
],
),
migrations.AddField(
model_name='b',
name='a',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='app.B'),
),
]
Migration 0003:
class Migration(migrations.Migration):
dependencies = ['app', '0002']
operations = [
migrations.AddField(
model_name='a',
name='field_2',
field=models.BooleanField(default=True),
),
]
Migration 0004:
class Migration(migrations.Migration):
dependencies = ['app', '0003']
operations = [
migrations.AddField(
model_name='a',
name='field_3',
field=models.BooleanField(default=True),
),
]
Migrated: 0001

Change Model's column attribute

I have an already migrated Django model, which was created this way:
operations = [
migrations.CreateModel(
name='Victim',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(max_length=200)),
('instagram', models.CharField(max_length=254)),
('old_password', models.CharField(blank=True, max_length=200)),
('new_password', models.CharField(blank=True, max_length=200)),
],
),
]
But now, I want to make email and instagram attribute Blank=True, but password fields make Blank=False.
What is the easiest way to do this: delete and recreate the model (data is not important) or is there a possible way to do this?
You can still change your models and run manage.py makemigrations. It will create another migration to execute the required SQL statements to alter your database schema when running manage.py migrate. This is the role of migrations.

Cannot generate foreign key field in Django

'authorid' is a foreign key to the Django 'User' model. After running 'makemigrations' and 'migrate' I can not see this field in the sqlite shell.
Here are my models,
class TopicModel(models.Model):
topic = models.CharField(max_length = 100)
topicAuthor = models.CharField(max_length = 100)
authorid = models.ForeignKey(User, related_name = 'id_of_author')
views = models.PositiveIntegerField(default = 0)
def __str__(self):
return self.topic
class PostModel(models.Model):
post = HTMLField(blank = True, max_length = 1000)
pub_date = models.DateTimeField('date published')
author = models.CharField(max_length = 30)
topicid = models.ForeignKey(TopicModel, related_name = 'posts')
def __str__(self):
return self.post
As you can see postmodel also has a foreign key to the topicmodel and there is no problem with this foreign key.
After migration the migrate file 0001_initial.py looks like this,
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import tinymce.models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='PostModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('post', tinymce.models.HTMLField(blank=True, max_length=1000)),
('pub_date', models.DateTimeField(verbose_name='date published')),
('author', models.CharField(max_length=30)),
],
),
migrations.CreateModel(
name='TopicModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('topic', models.CharField(max_length=100)),
('topicAuthor', models.CharField(max_length=100)),
('views', models.PositiveIntegerField(default=0)),
('authorid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='id_of_author', to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='postmodel',
name='topicid',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='posts', to='crudapp.TopicModel'),
),
]
In the sqlite shell the postmodel shows the field with the foreign key, which is topicid_id
sqlite> PRAGMA table_info(crudapp_postmodel);
0|id|integer|1||1
1|pub_date|datetime|1||0
2|author|varchar(30)|1||0
3|topicid_id|integer|1||0
4|post|text|1||0
But when I do the same with the topicmodel, the field with the foreign key doesn't exist, so there is no authorid field.
sqlite> PRAGMA table_info(crudapp_topicmodel);
0|id|integer|1||1
1|topic|varchar(100)|1||0
2|topicAuthor|varchar(100)|1||0
3|views|integer unsigned|1||0
Solution: As suggested by Alasdair I deleted the sqlitedb file and changed the fields from from topicid and authorid to topic and author.
Your current migration should create the foreign keys. My guess is that you updated the migration file after you had already created the crudapp_topicmodel table in the database.
If you don't have any important data yet, the easiest fix is to delete your sqlite file and rerun ./manage.py migrate.