2013-11-24 110 views
0

我正在使用xlrd读取Excel。其中一列具有银行名称,该名称通过外键链接到车辆型号。当xlrd读完一行时,它应该将该记录保存到车辆表中。然而,获取Vehicles.bank必须是Banks实例的实际pk值和错误。来自外键的Django模型实例

经过检查与这个问题有关的几十个问题后,我发现这个one是最相似的一个,但是我还没有得到预期的结果。

相关车辆模型部分如下:

class Vehicles(models.Model): 
    stock = models.CharField(max_length=10, blank=False, db_index=True) 
    vin = models.CharField(max_length=17, blank=False, db_index=True) 
    sold = models.DateField(blank=True, null=True, db_index=True) 
    origin = models.CharField(max_length=10, blank=False, db_index=True) 
    bank = models.ForeignKey('banks.Banks', db_column='bank', null=True) 
我使用python 2.7,Django的1.5.4和PostgreSQL 9.2.5

。 Dbshel​​l实用程序确实表明银行表具有涉及车辆表的外部限制,通过银行(id)。

由于我没有使用这个特定部分的表单,所以我认为使用ModelForm是否无关紧要。

当前场景:Excel文件具有FBANK作为单元格值。银行表中有一个存在的记录,其名称列中包含FBANK,id = 2。蟒蛇行是:

def bank(value): 
    return Banks.objects.get(name=value).id 

根据上述行,错误是: 不能分配“2”:“Vehicles.bank”必须是一个“银行”的实例。

如果我最后删除了“.id”,那么错误是: 银行匹配查询不存在。

感谢您的帮助。 Ricardo

回答

0

保存车辆时,您需要将银行实例与相应的银行名称一起传递。见例子,我想你在相应的单元格从0到4的所有数据,用自己的细胞用数字代替:

def get_bank_instance(bank_name): 
    try: 
     bank = Banks.objects.get(name=bank_name) 
    except Banks.DoesNotExist: 
     return None 
    return bank 

# reading excel file here, we have list of cells in a row 
for cell in cells: 
    bank = get_bank_instance(cell[4]) 
    if bank: 
     # get other cells values to be saved in Vehicles 
     stock, vin, sold, origin = cell[0], cell[1], cell[2], cell[3] 
     Vehicles.create(bank=bank, stock=stock, vin=vin, sold=sold, origin=origin) 

您还可以创建节约车辆通过银行ID直接实例:

b_id = Banks.objects.get(name=bank_name).id 
Vehicles.create(bank_id=b_id, stock=stock, vin=vin, sold=sold, origin=origin) 

更新: create()是创建并保存到数据库模型实例的内置模型方法。如果您在Django文档中询问“在模型类中添加类方法”,则不是这样,因为您只是使用模型的内置方法。对于某些情况,您可以使用自定义方法来创建新模型,但是如果必须为新实例传递很多默认属性,我会这样做。

此外,它可以创建和使用保存保存新的模型实例():

bank_instance = Banks.objects.get(name=bank_name) 
vehicle = Vehicles() 
vehicle.bank = bank_instance 
vehicle.stock = stock 
vehicle.vin = vin 
vehicle.sold = sold 
vehicle.origin = origin 
# without save() data will not be saved to db! 
vehicle.save() 

这是相当长的,你总是需要记住调用.save(),所以这是一个好主意使用.create()

+0

谢谢@nickzam。在测试了两个选项后,我最终使用了get_bank_instance选项。问题:我很难得到像Django页面上那样的选项的文档。具体而言,[模型实例引用](https://docs.djangoproject.com/en/1.5/ref/models/instances)并不表示与此类选项相关的任何内容。更重要的是,如果我搜索,是的,有多个页面,但没有具体的(或至少容易识别“哦,我需要做X或Y”。你有任何建议像这样的情况?谢谢 – Rmartin

+0

get_bank_instance只是我创建的一个帮助函数,用于说明如何返回模型实例。您应该查看https://docs.djangoproject.com/en/1.5/ref/models/querysets/#get https ://docs.djangoproject.com/en/1.5/ref/models/querysets/#create并在shell中运行(运行manage.py shell并导入模型),使用django模型和实例。 – nickzam

+0

感谢实际上,我使用的编码块类似于你添加的编码块(每场1行),因为有一些字段需要验证,其他字段也有一个外键,最重要的是,一些字段是必需的,所以如果Excel文件有一个空值或一个没有正确验证或者其外键没有如果不存在,我想警告用户并且不要创建该记录。 – Rmartin

0

当您想要将它分配给Vehicle模型实例时,您应该返回Banks实例;所以你不应该在你的bank()方法的返回值末尾有.id部分。其次,如果它表示它没有找到Banks实例,那么您应该检查您的value参数的值以查看它是什么,并尝试从数据库中手动执行Banks.objects.get。如果找不到,那么除了错误地使用Django ORM之外,可能还有另一个原因。

当您将实例分配给Django中的其他实例时,例如为汽车设置Bank时,它必须是模型的实例,而不是模型的id或pk值;这是你在你的问题中引用的另一个StackOverflow问题。