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

2 投票
1 回答
3982 浏览
提问于 2025-04-16 20:28

简短描述
我在本地使用sqlite3数据库时,可以保存和提取信息,但在我的生产服务器上(另一台机器上的postgresql 8.4),Django却报了一个“无法适应类型”的错误。有没有人能帮我指点一下,应该从哪里开始调试这个问题?

背景
这个Python项目使用Django 1.3来处理多个数据库(生产和调试)。在所有情况下,多个数据库连接都能正常工作,只有这个例外。在搜索StackOverflow和谷歌时,发现大多数类似的错误通过重新运行syncdb解决了。我在我的生产和调试服务器上都做过这个操作,但仍然遇到同样的错误。查看模型、访问器和修改器后,我无法看出这个函数有什么不同。我已经包含了可疑的函数、我的模型和错误信息。任何帮助都将非常感激。如果需要其他非敏感信息,我很乐意提供。

系统信息
* Postgresql 8.4 - Ubuntu服务器
* 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': '', 
            }
}

访问器 / 修改器

在调试和生产数据库上都能正常工作

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 个回答

6

原来在使用Django的过滤器时,sqlite3会忽略某些值,或者试图把这些值转换成字符串。我在图形界面中传入的是实际的底盘对象,而不是序列号。Postgresql在尝试把一个底盘对象当作序列号使用时会报错,而sqlite3则忽略了这个问题,把它当作字符串处理(我在Django中把它定义为序列号)。

我希望这个发现能帮助到其他人在调试类似错误时。

感谢所有关注这个问题的人。

撰写回答