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.3Models.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.
精彩评论