开发者

Django "can't adapt type" error using mutliple databases (Postgresql 8.4 and sqlite3)

Short Description

Using a local (sqlite3) database I can save and extract information, however when using my production sever (postgresql 8.4 on a different machine) Django throws a "can't adapt type" error. Can someone help point me in a good direction to start debugging this?

Background

The python project uses Django 1.3 for an ORM to multiple databases (production and debug). The multiple database connection works on in all cases but this one. In searching SO and Google, most of these errors were fixed by re-running syncdb. I have done this on both my production and debug server and still get the same error. After looking at the models, accessors and mutators I cannot see what is different about this function. I have included the suspect functions, my model, and error message. Any help would be greatly appreciated. I'll be glad to post any other, non sensitive, information needed.

System Information

* Postgresql 8.4 - Ubuntu Server

* Django Project (Client / Users)- Windows XP (as shown), Mac OSX, Windows 7 (64bit)

* 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 = mod开发者_JAVA百科els.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 Excerpt

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

Works on both debug and production database

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

Only works on debug database. See inline comments on the line if fails on

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

Error Message

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'


Turns out that sqlite3 ignores and or tries to convert a value to a string when using it in a Django filter. From the GUI I was passing in the actual chassis object rather than the serial number. Postgresql threw the error when trying to use a Chassis object as a serial number while sqlite3 ignored it and cast it as a string (which I defined in Django as the serial number).

I hope this discovery might help someone else when trying to debug this type of error.

Thanks for all who looked into this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜