'Django models sqlmigrate - too few arguments

Here are my Django models, which have multiple many to many relationships.

class Theme(models.Model):
        theme_name = Models.CharField(max_length=20)
        theme_ind = Models.CharField(max_length=1)

class Topics(models.Model):
        topic_name = Models.CharField(max_length=20)

class Language(models.Model):
        lang_name = models.CharField(max_length=10)


class Article(models.Model):
        name = Models.CharField(max_length=10)
        url = Models.CharField(max_length=50)
        lang_id = models.ManyToManyField(Language, related_name='theme')
        theme_id = models.OneToOneField(Theme, related_name='theme')
        topic_id = models.ManyToManyField(Topics, related_name='topic')

Question: When I run:

python  manage.py sqlmigrate polls

I get this error:

manage.py sqlmigrate: error: too few arguements.


Solution 1:[1]

You forgot the prefix of makemigrations command output file.

When you run:

python manage.py makemigrations polls

You will see in output 0001_any_name.py.

Here, 0001 is used in sqlmigrate for creating the database that you forgot to add in your command.

So, write:

python manage.py sqlmigrate polls 0001

Solution 2:[2]

From the docs, sqlmigrate also requires the migration name:

python manage.py sqlmigrate polls <migration_name>

Solution 3:[3]

I just ran across this, my issue: I'm making a lot of changes at once and I need to see all the migrations and I don't have time to go through each file and get the generated sql.

NOTE: The sql is NOT guaranteed to be in order, so if you have a migration that adds a field, and another that populates it, this might export the populating sql first causing your command to crash.

cat <<EOF | ./manage.py shell
from __future__ import print_function

import os
try:
    from StringIO import StringIO  # for Python 2
except ImportError:
    from io import StringIO  # for Python 3
from django.core.management import call_command
from django.apps import apps

# Remove all the terminal colors, less parsing later.
os.environ['DJANGO_COLORS'] = 'nocolor'

out = StringIO()
call_command('showmigrations', stdout=out)

# Clean up the line, and remove all applied migrations
work = [line.strip() for line in out.getvalue().split('\n') if not line.startswith(' [X]')]
# Keep looping until we run out of lines.
while work:
    app_name = work.pop(0)
    while work and work[0].startswith('['):
        migration_name = work.pop(0)[4:]
        app_path = apps.get_app_config(app_name).module.__file__
        # Print the whole path to the migration file that corresponds to this migration
        print('--', os.path.abspath(os.path.join(app_path, '../migrations/', '{}.py'.format(migration_name))))
        call_command('sqlmigrate', app_name, migration_name[:8])
EOF

This is very similar to the original solution, main difference is that now everything runs inside a single python process, that doesn't have to load up Django N times for every migration, speeding this up tremendously.


Old solution (slow)

It's hard to comment code in bash, so i'll do it here.

  1. get all the migrations.
  2. filter all migrations that have been applied.
  3. get python to give us a nice list of all the migrations that havent been applied format: <app> <4 digit migration code>\n
  4. use xargs to get every 2 fields, see above, and pipe it to sqlmigrate to get all the changes.
  5. patience, this is not the fastest.

Code:

./manage.py showmigrations | grep -v [X] | python <(cat <<EOF
from __future__ import print_function  # just in case
import sys

work = [line.strip() for line in sys.stdin]    
while work:
    header = work.pop(0)
    while work and work[0].startswith('['):
      print(header, work.pop(0)[4:8])
EOF
) | xargs -n 2 ./manage.py sqlmigrate

Solution 4:[4]

sqlmigrate is for printing the sql that will be part of a migration

There should be one more argument, as the error suggests:

sqlmigrate app_label migrationname

See: https://docs.djangoproject.com/en/1.8/ref/django-admin/#django-admin-sqlmigrate

Perhaps you're trying to do something like this:

python manage.py makemigrations polls
python manage.py migrate

Solution 5:[5]

Whenever you create a table or add changes to existing table you need to run 3 commands:

  1. python manage.py makemigrations app_name
  2. python manage.py sqlmigrate app_name migration_name
  3. python manage.py migrate

It seems that you have missed providing the migration name as mentioned in point 2

Solution 6:[6]

You have to run this command:

python manage.py sqlmigrate polls 0001  

Solution 7:[7]

to get all migrations in order you could use showmigrations -p

and you could add it to Javier solution for generating all the SQL statement in order

import os
import django
from io import StringIO
from django.core.management import call_command
from django.apps import apps
import re

# Remove all the terminal colors, less parsing later.
os.environ['DJANGO_COLORS'] = 'nocolor'
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
django.setup()

out = StringIO()
call_command('showmigrations', '-p', stdout=out)

# Clean up the line, and remove all applied migrations
migrations = [line.strip() for line in out.getvalue().split('\n')]

migration_regex = re.compile('^\[[X ]\]  ([^.]*).(.*)$')


with open('sql_script.sql', 'w') as out_file:
    
    for migration in migrations:
        searched_migration = re.search(migration_regex, migration)
        if searched_migration:
            app_name = searched_migration.group(1)
            migration_name = searched_migration.group(2)
            app_path = apps.get_app_config(app_name).module.__file__
            call_command('sqlmigrate', app_name, migration_name, stdout=out_file)
                    

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 user2687058
Solution 5 Pratik Randad
Solution 6 theUtherSide
Solution 7 Amr Hashem