使用多个数据库的Django“无法适应类型”错误(Postgresql 8.4和sqlite3)

时间:2011-06-28 17:20:13

标签: python database django

简短描述
使用本地(sqlite3)数据库我可以保存和提取信息,但是当使用我的生产服务器(在不同的机器上的postgresql 8.4)时,Django会抛出“无法适应的类型”错误。有人可以帮助我指出一个好的方向来开始调试吗?

背景
python项目使用Django 1.3将ORM用于多个数据库(生产和调试)。多个数据库连接在所有情况下都可以使用,但是这个。在搜索SO和Google时,大多数错误都是通过重新运行syncdb来解决的。我已经在我的生产和调试服务器上完成了这个并且仍然得到相同的错误。在查看模型,访问器和变换器后,我看不出这个函数有什么不同。我已经包含了可疑功能,我的模型和错误消息。任何帮助将不胜感激。我很乐意发布所需的任何其他非敏感信息。

系统信息
* Postgresql 8.4 - Ubuntu Server
* Django项目(客户端/用户) - Windows XP(如图所示),Mac OSX,Windows 7(64位)
* Python 2.7.1
* Psycopg2
* Django 1.3

Models.py

from django.db import models

# Create your models here.
class Card_Test(models.Model):
    name = models.TextField(max_length=100)
    description = models.TextField(max_length=200)
    units = models.TextField(max_length=500)
    result_tags = models.TextField(max_length=500)

    def __unicode__(self):
        return self.name

class Status_Type(models.Model):
    status = models.CharField(max_length=25)

    def __unicode__(self):
        return self.status

class Card_Test_List(models.Model):
    card_id = models.ForeignKey('Card')
    card_test_id = models.ForeignKey('Card_Test')
    card_test_sub_id = models.PositiveIntegerField()
    status       = models.ForeignKey('Status_Type')
    result       = models.TextField()
    ran_on       = models.DateField()
    ran_by       = models.CharField(max_length=50)
    run_number   = models.PositiveIntegerField()

    def __unicode__(self):
        return self.card_test_id.__unicode__()

class Card_Type(models.Model):
    card_type = models.CharField(max_length=25)

    def __unicode__(self):
        return self.card_type

class Card(models.Model):
    serial_number = models.CharField(max_length=25)
    card_type = models.ForeignKey('Card_Type')
    status = models.ForeignKey('Status_Type')
    card_tests = models.ManyToManyField('Card_Test', through='Card_Test_List')

    def __unicode__(self):
        return self.serial_number

    def print_all_cards(self):
        print Card.objects.all()

class System_Test_Type(models.Model):
    test_type = models.CharField(max_length=25)

    def __unicode__(self):
        return self.test_type

class System_Test(models.Model):
    name        = models.CharField(max_length=100)
    description = models.CharField(max_length=100)
    units       = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name


class System_Test_List(models.Model):
    chassis_id = models.ForeignKey('Chassis')
    system_test_id = models.ForeignKey('System_Test') 
    result     = models.CharField(max_length=25)
    ran_on     = models.DateField()
    ran_by     = models.CharField(max_length=50)
    test_type  = models.ForeignKey('System_Test_Type')

    def __unicode__(self):
        return self.system_test_id.__unicode__()

class Chassis(models.Model):
    serial_number = models.CharField(max_length=25)
    slot_311 = models.ForeignKey(Card, related_name='slot1_card')
    slot_175 = models.ForeignKey(Card, related_name='slot2_card')
    slot_345 = models.ForeignKey(Card, related_name='slot3_card')
    slot_346 = models.ForeignKey(Card, related_name='slot4_card')
    slot_344 = models.ForeignKey(Card, related_name='slot5_card')
    slot_178 = models.ForeignKey(Card, related_name='slot6_card')
    backplane_serial = models.TextField(max_length=25)
    site_location    = models.TextField(max_length=25)
    status_env_70c  = models.ForeignKey('Status_Type', related_name='70C')
    status_env_10c  = models.ForeignKey('Status_Type', related_name='10C')
    status_assembly = models.ForeignKey('Status_Type', related_name='assembly')
    status_final    = models.ForeignKey('Status_Type', related_name='final')
    system_test = models.ManyToManyField(System_Test, through='System_Test_List')

    def __unicode__(self):
        return self.serial_number

Settings.py 摘录

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'production',                    # Or path to database file if using sqlite3.
        'USER': 'tester',                      # Not used with sqlite3.
        'PASSWORD': 'xxxxxx',                  # Not used with sqlite3.
        'HOST': '10.10.100.30',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
                  },
    'debug': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': curdir + '/mux_db',
        'USER': '',                     
        'PASSWORD': '',                 
        'HOST': '',                     
        'PORT': '', 
            }
}

Accssors / Mutators

适用于调试和生产数据库

def get_chassis_by_sn(chassis_id):
    try:
        return Chassis.objects.using(get_database()).filter(serial_number__iexact=chassis_id)
    except Chassis.DoesNotExist:
        return []

仅适用于调试数据库。如果

失败,请在该行上查看内联注释
def modify_chassis_sn(current, new):
    #chassis = Chassis.objects.using(get_database()).filter(serial_number__iexact=current)
    try:
        chassis = Chassis.objects.using(get_database()).filter(serial_number__iexact=current)
    except Chassis.DoesNotExist:
        err.Handle_MUX_Error('Unknown Chassis / Serial Number')
        return False
    chassis = chassis[0] # <--- Fails here

    # Update the serial number
    chassis.serial_number = new
    chassis.save(using=get_database())
    return True

def modify_chassis_record(sn, slots=None, bp_sn=None, site_loc=None ):

    #chassis = Chassis.objects.using(get_database()).filter(serial_number__iexact=sn)

    try:
        c = Chassis.objects.using(get_database()).filter(serial_number__iexact=sn)
        print len(c)
    except Chassis.DoesNotExist:
        err.Handle_MUX_Error('Unknown Chassis / Serial Number')
        return False
    chassis = c[0]  # <--- Fails here

    # Update the List of Cards (if provided)
    if slots != None:
        if len(slots) != 6:
            err.Handle_MUX_Error('You must enter 6 serial numbers!')
            return False

        index = 0
        db_slots = [None]*6
        for slot in slots:
            s = get_card_by_sn(slot)

            if len(s) == 0:
                err.Handle_MUX_Error('Slot ' + str(index) + ' serial number does not exist!')
                return False

            db_slots[index] = s[0]
            index +=1

        chassis.slot_311 = db_slots[0]
        chassis.slot_175 = db_slots[1]
        chassis.slot_345 = db_slots[2]
        chassis.slot_346 = db_slots[3]
        chassis.slot_344 = db_slots[4]
        chassis.slot_178 = db_slots[5]

    # Update the Backplane Serial Number (if provided)
    if bp_sn != None:
        chassis.backplane_serial = bp_sn

    # Update the site Location (if provided)
    if site_loc != None:
        chassis.site_location = site_loc

    # Save all changes to the chassis
    print chassis
    chassis.save(using=get_database())
    return True

错误消息

Traceback (most recent call last):
  File "C:\Documents and Settings\User\Desktop\Python\exe\wx_gui\Assembly_Panel.py", line 276, in SaveChassis
    mux_api.modify_chassis.run(active_chassis, new_chassis_id, bp_sn=backplane_sn)
  File "C:\Documents and Settings\User\Desktop\Python\exe\api_rehabilitation_suite\modify_chassis.py", line 10, in run
    modify_status = db.modify_chassis_record(sn, slots=slots, bp_sn=bp_sn, site_loc=site_loc )
  File "C:\Documents and Settings\User\Desktop\Python\mux_test_data\db_driver.py", line 136, in modify_chassis_record
    print len(c)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 82, in __len__
    self._result_cache = list(self.iterator())
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 273, in iterator
    for row in compiler.results_iter():
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 680, in results_iter
    for rows in self.execute_sql(MULTI):
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\postgresql_psycopg2\base.py", line 44, in execute
    return self.cursor.execute(query, args)
django.db.utils.DatabaseError: can't adapt type 'Chassis'

1 个答案:

答案 0 :(得分:4)

事实证明,当在Django过滤器中使用它时,sqlite3会忽略和/或尝试将值转换为字符串。从GUI我传递的是实际的机箱对象而不是序列号。当尝试使用Chassis对象作为序列号时,Postgresql抛出错误,而sqlite3忽略它并将其转换为字符串(我在Django中将其定义为序列号)。

我希望在尝试调试此类错误时,此发现可能会帮助其他人。

感谢所有关注此事的人。