Django 1.4:获取外键对象中的字段(null = True),获取None或字段值

时间:2012-04-10 22:36:31

标签: python django

假设我有这些模型:

class A(models.Model):
    name = models.CharField(max_length=32)
    b = models.ForeignKey("B", null=True)
    def __unicode__(self):
        return self.name

class B(models.Model):
    name = models.CharField(max_length=32)
    def __unicode__(self):
        return self.name

这个观点:

def DisplayIt(request):
    html = ""
    for a in A.objects.all():
        html += "<input type='text' value='" + a.b.name + "' />"

只要每个A在字段b中引用B,这都可以正常工作。但是,我在b参考字段上有null = True。当b为None时,抛出一个异常,即NoneType没有函数名,这是完全可以预期的。

显然,我可以这样做:

def DisplayIt(request):
    somestring = ""
    for a in A.objects.all():
        if a.b is not None:
            somestring += a.b.name

但是,如果我不需要,我不想这样做。那么,如果b是None,有没有办法获得b.name或None,没有在每个循环中放置if a.b is not None:?我的真实世界的例子要复杂得多,我正在创建一个临时对象,用于显示实际数据库字段......足以说我不想拥有所有那些if语句,并且不确定是否存在到达那里是另一个内置功能。我还可以创建一个类方法来获取每个外部字段(如果它们存在)或空白(如果它们不存在),但我不确定这是最好的方法。

2 个答案:

答案 0 :(得分:3)

让数据库为您完成。

使用cross-relation filter获取A b name def DisplayIt(request): somestring = "" for a in A.objects.filter(b__name__isnull=False): somestring += a.b.name not null的所有a.b

def DisplayIt(request):
    somestring = ""
    for a in A.objects.filter(b__name__isnull=False):
        somestring += a.b.name
    for a in A.objects.filter(b__name__isnull=True):
        somestring += "dummy value for missing b.name"

要执行此操作,以便在def DisplayIt(request): stringparts = [] for a in A.objects.filter(b__name__isnull=False): stringparts.append(a.b.name) for a in A.objects.filter(b__name__isnull=True): stringparts.append("dummy value for missing b.name") ''.join(stringparts) 为None时包含虚拟值,请使用以下命令:

def DisplayIt(request):
    stringparts = []
    for a in A.objects.filter(b__name__isnull=False).select_related():
        stringparts.append(a.b.name)
    for a in A.objects.filter(b__name__isnull=True).select_related():
        stringparts.append("dummy value for missing b.name")
    ''.join(stringparts)

<小时/>

另外,作为旁注,不要那样做字符串连接 - 它是horribly inefficient,因为Python字符串不可变。以下是更好的:

{{1}}

<小时/>

第二方注意:上面的代码将执行查询以在for循环的每次迭代中获取a.b.这可能是缓慢的。考虑使用select_related一次性抓取所有内容。但要小心 - 如果索引设置不正确,这也可能很慢。启用此功能后,我会嗅探查询并spend some quality time with your query planner以确保您没有进行任何令人讨厌的非索引查找。

修订代码:

{{1}}

答案 1 :(得分:3)

建立你的评论,说你想要A的实例,可能有也可能没有B.你可以破解它的工作,这通常是一个可怕的想法。使用您想要避免的冗长的pythonic方式。但这是糟糕的方式来做你想做的事情:

a.__dict__.get('b',{'name':None}).name

这使用了以下事实:所有属性都存储在对象的实际实例上的dict对象中。您使用标准字典存取器get()返回b或包含您感兴趣的属性的字典。这是一个可怕的想法,但确实如此。

另外,django / python不是老派PHP。我不敢相信我在过去几周里在stackoverflow上看过多少次这样的事情,但是...... 不要强调使用HTML来生成HTML !! 这就是模板语言的用途。用它。现在就停止你正在做的事情。停止它停止它停止它。使用模板,不要尝试在视图中编写HTML。这是一个可证明错误的事情,所以停下来。停下来。