如何管理非默认的Django数据库

7
我是一个有用的助手,可以翻译文本。
我在使用Django(v1.8)应用程序中的非默认数据库时遇到了问题。当我尝试进行makemigrations和迁移时,PostgreSQL数据库没有得到更新。
这是我的Django结构:
fbrDjangoSite
|-- db.sqlite3
|-- manage.py
|-- fbrDjangoSite
|   |-- __init__.py
|   |-- requirements.txt
|   |-- settings.py
|   |-- urls.py
|   |-- wsgi.py
|-- fbrPostHasteAppV0_1
|   |-- __init__.py
|   |-- admin.py
|   |-- migrations
|   |-- models.py
|   |-- router.py
|   |-- tests.py
|   |-- urls.py
|   |-- views.py

fbrPostHasteAppV0_1/admin.py

from django.contrib import admin
from fbrPostHasteAppV0_1.models import MusicianTable   # gvim ../fbrPostHasteAppV0_1/models.py +/MusicianTable
from fbrPostHasteAppV0_1.models import AlbumTable      # gvim ../fbrPostHasteAppV0_1/models.py +/AlbumTable

# Register your models here.
admin.site.register(MusicianTable)
admin.site.register(AlbumTable)

fbrPostHasteAppV0_1/models.py

from django.db import models

# Define your models/tables here.
class MusicianTable(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

    class Meta:
        managed = True

class AlbumTable(models.Model):
    artist = models.ForeignKey(MusicianTable)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

    class Meta:
        managed = True

fbrPostHasteAppV0_1/router.py

class fbrPostHasteAppV0_1Router(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'fbrPostHasteAppV0_1':
            return 'fbrPostHasteDbV0_1'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'fbrPostHasteAppV0_1':
            return 'fbrPostHasteDbV0_1'
        return None

    def allow_syncdb(self, db, model):
        if db == 'fbrPostHasteDbV0_1':
            return model._meta.app_label == 'fbrPostHasteAppV0_1'
        elif model._meta.app_label == 'fbrPostHasteAppV0_1':
            return False
        return None

fbrDjangoSite/settings.py

# ...
INSTALLED_APPS = (
    # ...
    'fbrPostHasteAppV0_1',             # v ../fbrPostHasteAppV0_1/__init__.py
)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    # ...
    'fbrPostHasteDb': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'fbrPostHasteDbV0_1',
        'USER': 'myuser',
        'PASSWORD': '',
        'HOST': 'myhost.us.overlord.com',
        'PORT': '0000',
    },
}

DATABASE_ROUTERS = ['fbrPostHasteAppV0_1.router.fbrPostHasteAppV0_1Router',]

这是我运行迁移命令时的输出结果:
[fbrDjangoServerV0_1.venv.py] /<3>django/fbrDjangoServerV0_1.venv.py/fbrDjangoSite> python manage.py makemigrations fbrPostHasteAppV0_1 --verbosity 3
    /fobar-tools/pylibs/lib/python/Django-1.8-py2.7.egg/django/db/models/base.py:1497: RemovedInDjango19Warning: Router.allow_syncdb has been deprecated and will stop working in Django 1.9. Rename the method to allow_migrate.
      if not router.allow_migrate(db, cls):
    Did you rename the fbrPostHasteAppV0_1.Musician model to MusicianTable? [y/N] y
    Migrations for 'fbrPostHasteAppV0_1':
      0002_auto_20150408_1653.py:
        - Create model AlbumTable
        - Rename model Musician to MusicianTable
        - Remove field artist from album
        - Delete model Album
        - Add field artist to albumtable
[fbrDjangoServerV0_1.venv.py] /<3>django/fbrDjangoServerV0_1.venv.py/fbrDjangoSite> python manage.py migrate --verbosity 3 
    /fobar-tools/pylibs/lib/python/Django-1.8-py2.7.egg/django/db/models/base.py:1497: RemovedInDjango19Warning: Router.allow_syncdb has been deprecated and will stop working in Django 1.9. Rename the method to allow_migrate.
      if not router.allow_migrate(db, cls):
    Operations to perform:
      Synchronize unmigrated apps: staticfiles, messages
      Apply all migrations: fbrSimDataV0_2, sessions, admin, polls, auth, contenttypes, fbrPostHasteAppV0_1
    Synchronizing apps without migrations:
    /fobar-tools/pylibs/lib/python/Django-1.8-py2.7.egg/django/db/utils.py:336: RemovedInDjango19Warning: Router.allow_syncdb has been deprecated and will stop working in Django 1.9. Rename the method to allow_migrate.
      return [model for model in models if self.allow_migrate(db, model)]
      Creating tables...
      Installing custom SQL...
      Installing indexes...
    Running migrations:
      Applying fbrPostHasteAppV0_1.0002_auto_20150408_1653.../fobar-tools/pylibs/lib/python/Django-1.8-py2.7.egg/django/db/migrations/operations/base.py:107: RemovedInDjango19Warning: Router.allow_syncdb has been deprecated and will stop working in Django 1.9. Rename the method to allow_migrate.
      router.allow_migrate(connection_alias, model) and
     OK
    /fobar-tools/pylibs/lib/python/Django-1.8-py2.7.egg/django/contrib/auth/management/__init__.py:70: RemovedInDjango19Warning: Router.allow_syncdb has been deprecated and will stop working in Django 1.9. Rename the method to allow_migrate.
      if not router.allow_migrate(using, Permission):
    The following content types are stale and need to be deleted:
        fbrPostHasteAppV0_1 | album
        fbrPostHasteAppV0_1 | musician

但是当我查看数据库时,“表格”并未被添加。
[fbrDjangoServerV0_1.venv.py] /<3>django/fbrDjangoServerV0_1.venv.py/fbrDjangoSite>       psql -h localhost -p 0000 --command "\l" postgres
                                 List of databases
       Name    |  Owner   | Encoding  | Collate | Ctype |   Access privileges
    -----------+----------+-----------+---------+-------+-----------------------
     postgres  | myuser   | SQL_ASCII | C       | C     |
     template0 | myuser   | SQL_ASCII | C       | C     | =c/myuser          +
               |          |           |         |       | myuser=CTc/myuser
     template1 | myuser   | SQL_ASCII | C       | C     | =c/myuser          +
               |          |           |         |       | myuser=CTc/myuser
     test      | myuser   | SQL_ASCII | C       | C     |
    (4 rows)

我原本认为Django可以创建表格,并在我对模型进行更改时保持同步。我的理解正确吗?如果是的话,我在这里做错了什么?
更新:我的一个问题是我的路由器代码基于旧版本的Django。我现在不确定这是否完全正确,但它与文档非常相似:https://docs.djangoproject.com/en/1.8/topics/db/multi-db/
class fbrPostHasteAppV0_1Router(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'fbrPostHasteAppV0_1':
            return 'fbrPostHasteDbV0_1'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'fbrPostHasteAppV0_1':
            return 'fbrPostHasteDbV0_1'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'fbrPostHasteAppV0_1' or \
           obj2._meta.app_label == 'fbrPostHasteAppV0_1':
           return True
        return None

    def allow_migrate(self, db, app_label, model=None, **hints):
        if app_label == 'fbrPostHasteAppV0_1':
            return db == 'fbrPostHasteDbV0_1'
        return None

另一个问题是我没有使用 --database 参数调用 migrate 命令:
 python manage.py migrate --database=fbrPostHasteDb

但现在我又遇到了另一个错误:
django.db.utils.OperationalError: FATAL:  database "fbrPostHasteDbV0_1" does not exist

继续找出我还搞砸了什么...
更新2
所以我是这样创建数据库的:
psql -h localhost -p 8080 --command "CREATE DATABASE fbrPostHasteDbV0_1"

但它创建了fbrposthastedbv0_1。

因此,一旦我更改了所有引用和名称,我就能够:

python manage.py migrate --database=fbrPostHasteDb

$ ./manage.py migrate --database=fbrPostHasteDb,能否给我你的调试信息?可能是因为在postgres中更改某些字段也需要手动操作,一个月前我不得不将一个varchar字段更改为text字段,发现迁移并没有影响到该列,所以我被迫手动操作。 - Mikeec3
它在那里。有点难看到,在代码片段底部的第二个,约三分之一处。我展示的是一个ALTER,但我最初在psql中没有这个表,所以我预计它会进行CREATE,但它没有这样做。 - stephenmm
2个回答

1

那有点糟糕。我选择Postgres是因为它似乎是Django最好支持的,可以帮我进行迁移...我想知道是否应该改用MySQL。 - stephenmm
1
到目前为止,这似乎是一个多数据库的“文档混乱”和用户错误问题,与PostgreSQL无关。 - stephenmm

0

我的一个问题是我的路由器代码基于旧版本的Django。我不确定现在是否完全正确,但它与文档非常相似:https://docs.djangoproject.com/en/1.8/topics/db/multi-db/

class fbrPostHasteAppV0_1Router(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'fbrPostHasteAppV0_1':
            return 'fbrPostHasteDbV0_1'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'fbrPostHasteAppV0_1':
            return 'fbrPostHasteDbV0_1'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'fbrPostHasteAppV0_1' or \
           obj2._meta.app_label == 'fbrPostHasteAppV0_1':
           return True
        return None

    def allow_migrate(self, db, app_label, model=None, **hints):
        if app_label == 'fbrPostHasteAppV0_1':
            return db == 'fbrPostHasteDbV0_1'
        return None

另一个问题是我没有使用 --database 参数调用迁移命令:
 python manage.py migrate --database=fbrPostHasteDb

但是现在我又遇到了另一个错误:

django.db.utils.OperationalError: FATAL:  database "fbrPostHasteDbV0_1" does not exist

继续找出我还搞砸了什么...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接