7

Edit: There seems to be some confusion about what I'm asking. That model is for the Postgres view that I created in migration 0009. I was under the impression that Django won't generate a migration for a model if it has the managed = False option. However, it's still trying to create it.

Also, I'm using Django 1.8 with Python 3.4.

I'm having trouble creating a Django model for a Postgres view, using these links as a guide: drdaeman and eceppda's answer in Can I use a database view as a model in django. I also looked up the Options.managed entry in Django's API docs. However, even with this, it's creating a migration that adds a table for the view's model.

This is my code so far:

foo/models.py

class RelevantModel(models.Model):
    rebate_pool_total = models.OneToOneField('foo.VirtualTotal', null=True)
    total = models.DecimalField(null=True, decimal_places=2, max_digits=32)

class VirtualTotal(models.Model):
    relevant_model = models.ForeignKey('foo.RelevantModel')
    total = models.DecimalField(null=True, decimal_places=2, max_digits=32)

    class Meta:
        managed = False

foo/migrations/0009_add_foo_view.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('foo', '0008_previous_migration'),
    ]

    sql = """
    create VIEW foo_virtualtotal AS
      SELECT rest of view...
    """

    operations = [
        migrations.RunSQL('DROP VIEW IF EXISTS foo_virtualtotal;'),
        migrations.RunSQL(sql)
    ]

What am I doing wrong?

e4c5
  • 52,766
  • 11
  • 101
  • 134
NJP
  • 815
  • 1
  • 7
  • 20
  • There's no migration here that creates a table as you have described. This migration shows custom code that you have put in there – e4c5 Jun 30 '16 at 10:06
  • I know. When I generate migrations for that app after that, it's still trying to create a table for the VirtualTotal model. I was under the impression that `managed = False` tells Django to not generate migrations for that table. – NJP Jun 30 '16 at 15:23
  • what makes you say that? – e4c5 Jun 30 '16 at 23:35
  • That's how I interpreted the API documentation on `Options.managed`: https://docs.djangoproject.com/en/1.8/ref/models/options/#managed. Am I misinterpreting it? I first read about it in this SO answer: http://stackoverflow.com/questions/507795/can-i-use-a-database-view-as-a-model-in-django/1281051#1281051. – NJP Jul 01 '16 at 16:20

1 Answers1

11

Django does create a migration for each newly added table in your app regardless of whether it's a managed model or not. However there is a very important and subtle difference when you use the managed=False setting. The resultant migration is a dummy entry. It does not execute any SQL at all.

To confirm this add a new model that is unmanaged

class Dummy(models.Model):
    something = models.IntegerField()

    class Meta:
       managed = False

now when you do makemigrations followed by sqlimigrate *myapp* *migration_number* you will see that it doesn't produce any sql.

If on the other hand, you do find that Django is trying to create a table for you, that usually means that you had the same model in existence earlier but at the time the model was managed. To confirm this, search your migrations folder for VirtualTotal which is the name of the model in question.

e4c5
  • 52,766
  • 11
  • 101
  • 134