0

I believe these two are related.

I’m having two migration issues:

  1. I added a new file with two new classes (database tables).
  2. The tables are to be added to the local MySQL database (5.5).
  3. I have routers to other databases, but not the my local MySQL (developed under 1.5).
  4. I’m running Django 1.8.8 (recently updated from 1.6 via 1.7) and Python 2.7.6.
  5. The first problem I had was that Django did not recognize that I had added the new tables in the new file.
  6. I gave up on the new file (I have 6 other models_*.py files for this app that worked great under South) and just put the new classes in one of the existing files.
  7. Now makemigrations detected the changes and said it applied the changes. But the new tables did not appear in the database.

History

MY INITIAL MIGRATION (done during 1.7 upgrade):

$ ./manage.py makemigrations -v 3 sanity
Migrations for 'sanity':
  0001_initial.py:
- Create model Alert_User_Criteria
...
- Create model Test_Machine

$ ./manage.py migrate -v 3 --fake sanity
Operations to perform:
Apply all migrations: sanity0
Running pre-migrate handlers for application admin 
...
Running migrations:
Rendering model states... DONE (0.296s)
  Applying sanity.0001_initial... FAKED (0.010s)
Running post-migrate handlers for application admin
...
Running post-migrate handlers for application staff_status

migrations/$ ls -al
-rw-rw-r-- 1  21731 Jan 25 16:06 0001_initial.py
-rw-rw-r-- 1   9953 Jan 25 16:06 0001_initial.pyc
-rw-rw-r-- 1         0 Jan 14 12:14 __init__.py
-rw-rw-r-- 1     142 Jan 25 16:06 __init__.pyc

mysql> select * from  django_migrations;
+----+---------------+---------------------------------------+---------------------+
| id | app           | name                                  | applied             |
+ ----+---------------+---------------------------------------+---------------------+
|  1 | contenttypes  | 0001_initial                          | 2016-01-12 11:56:34 |
|  2 | auth          | 0001_initial                          | 2016-01-12 11:56:34 |
|  3 | admin         | 0001_initial                          | 2016-01-12 11:56:34 |
. . .
| 30 | sanity        | 0001_initial                          | 2016-01-25 16:06:52 |
+----+---------------+---------------------------------------+---------------------+

NEW FILE: MODELS_SA.PY

from django.db   import models
from django.conf import settings

class Archive_Control(models.Model):
config_name  = models.CharField(max_length=128, null=False, unique=True, db_index=True)
is_active    = models.BooleanField(default=True)
oldest_build = models.DateTimeField(auto_now_add=True)
newest_build = models.DateTimeField(auto_now_add=True)
archive_url  = models.CharField(max_length=128, null=True)

def __unicode__(self):
    return self.config_name

class Meta:
    app_label = 'sanity'
    ordering = ['config_name']

class Build_Archives(models.Model):
config         = models.ForeignKey(Archive_Control, db_index=True)
gcid           = models.CharField(max_length=16, null=True)
build_nbr      = models.CharField(max_length=16, null=True)
build_url      = models.CharField(max_length=128, null=True)
build_datetime = models.DateTimeField(null=True)

def __unicode__(self):
    return self.config+" : "+str(self.build_datetime)

class Meta:
    app_label = 'sanity'
    ordering = ['build_datetime']
    get_latest_by = 'build_datetime'

def get_sortable_build_datetime(self):
    return self.build_datetime.strftime("%Y%m%d%H%M%S")
def get_formatted_build_datetime(self):
    return self.build_datetime.strftime("%Y-%m-%d %H:%M:%S")

build_datetime_sortable  = property(get_sortable_build_datetime)
build_datetime_formatted = property(get_formatted_build_datetime)

RUN MAKEMIGRATIONS WITH NEW FILE

$ ./manage.py makemigrations -v 3 sanity
No changes detected in app 'sanity'

ADDED CONTENTS OF MODELS_SA.PY TO MODELS.PY

$ ./manage.py makemigrations -v 3 sanity
Migrations for 'sanity':
  0002_archive_control_build_archives.py:
  - Create model Archive_Control
  - Create model Build_Archives

Why did it work now?

$ ./manage.py migrate -v 3 sanity
Operations to perform:
  Apply all migrations: sanity
Running pre-migrate handlers for application admin
. . .
Running migrations:
  Rendering model states... DONE (0.275s)
  Applying sanity.0002_archive_control_build_archives... OK (0.072s)
Running post-migrate handlers for application admin
...
Running post-migrate handlers for application staff_status


migrations$ ls -al
total 64
-rw-rw-r-- 1  21731 Jan 25 16:06 0001_initial.py
-rw-rw-r-- 1    9953 Jan 25 16:06 0001_initial.pyc
-rw-rw-r-- 1    1669 Jan 25 16:11 0002_archive_control_build_archives.py
-rw-rw-r-- 1    1673 Jan 25 16:12 0002_archive_control_build_archives.pyc
-rw-rw-r-- 1          0 Jan 14 12:14 __init__.py
-rw-rw-r-- 1      142 Jan 25 16:06 __init__.pyc

migrations$ cat 0002_archive_control_build_archives.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

dependencies = [
('sanity', '0001_initial'),
]

operations = [
migrations.CreateModel(
    name='Archive_Control',
    fields=[
        ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
        ('config_name', models.CharField(unique=True, max_length=128, db_index=True)),
        ('is_active', models.BooleanField(default=True)),
        ('oldest_build', models.DateTimeField(auto_now_add=True)),
        ('newest_build', models.DateTimeField(auto_now_add=True)),
        ('archive_url', models.CharField(max_length=128, null=True)),
    ],
    options={
        'ordering': ['config_name'],
    },
),
migrations.CreateModel(
    name='Build_Archives',
    fields=[
        ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
        ('gcid', models.CharField(max_length=16, null=True)),
        ('build_nbr', models.CharField(max_length=16, null=True)),
        ('build_url', models.CharField(max_length=128, null=True)),
        ('build_datetime', models.DateTimeField(null=True)),
        ('config', models.ForeignKey(to='sanity.Archive_Control')),
    ],
    options={
        'ordering': ['build_datetime'],
        'get_latest_by': 'build_datetime',
    },
),
]


mysql> select * from  django_migrations;
+----+---------------+---------------------------------------+---------------------+
| id | app           | name                                  | applied             |
+----+---------------+---------------------------------------+---------------------+
. . .
| 30 | sanity        | 0001_initial                          | 2016-01-25 16:06:52 |
| 31 | sanity        | 0002_archive_control_build_archives   | 2016-01-25 16:12:17 |
+----+---------------+---------------------------------------+---------------------+

TABLES ARE NOT IN THE DATABASE!

I have already read:

Community
  • 1
  • 1
user3130740
  • 91
  • 1
  • 6

1 Answers1

0

From the docs on migrations:

That in-memory structure is also used to work out what the differences are between your models and the current state of your migrations; Django runs through all the changes, in order, on an in-memory set of models to come up with the state of your models last time you ran makemigrations. It then uses these models to compare against the ones in your models.py files to work out what you have changed.

(Emphasis mine)

Since models_sa.py isn't a models.py file, it is ignored, hence when you move its contents to a models.py, its changes are applied.

I realise the docs link is for a newer version but the principles shown are the same

Sayse
  • 42,633
  • 14
  • 77
  • 146
  • Sayse, 1. South did not have that limitation. I have lots and lots of models_xxx.py files in all of my applications. I read the above except from the migrations documentation as being "generically" my models.py files, not "literally" my models.py file per app. 2. Any idea why it said it applied the changes by did not add the tables to the database? This is the first true migration I have tried since switching from South to migrations. – user3130740 Jan 26 '16 at 20:55
  • @user3130740 - I think generally django tries to keep things organised (simple?) with uniformed file names, hence the sole models.py. How do you actually verify that the tables aren't added? Your mysql command just seems to be looking whats in the `django_migrations` table (disclaimer: I don't use mysql) – Sayse Jan 27 '16 at 07:50
  • @user3130740 - in case you haven't seen it also, there is a section in the docs about [upgrading from south](https://docs.djangoproject.com/en/1.9/topics/migrations/#upgrading-from-south) – Sayse Jan 27 '16 at 15:05
  • @user3130740: I use MySQL command line interpreter to 'show tables;'. The new tables are not there. – user3130740 Jan 27 '16 at 23:36
  • @user3130740 - I'm not fully convinced that the table isn't created (I can't think of a logical reason why it wouldn't be). Have you tried creating an instance to verify it that way? (`Archive_Control.objects.create()`...) – Sayse Jan 28 '16 at 10:12
  • @user3130740: >>> from sanity.models import Archive_Control >>> Archive_Control.objects.create() Traceback (most recent call last): ... File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 205, in execute self.errorhandler(self, exc, value) File "/usr/local/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler raise errorclass, errorvalue ProgrammingError: (1146, "Table 'graphic_tools.sanity_archive_control' doesn't exist") – user3130740 Jan 29 '16 at 18:43
  • I have tried everything I could find on all StackOverflow posts. – user3130740 Feb 01 '16 at 15:31
  • FIXED IT Turns out that I need to now (Django >= 1.7) create a ROUTER for the Graphics Tools database so that it will return allow_migrate() = True. Previously you only needed routers for databases that were NOT managed locally. From the Stack Overflow posting: Note that migrations will just silently not perform any operations on a model for which [allow_migrate] returns False. REF: https://docs.djangoproject.com/en/1.7/topics/db/multi-db/ – user3130740 Mar 15 '16 at 16:19