2

假设我有这些模型:

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 语句,并且不确定是否存在是到达那里的另一个内置功能。我还可以创建一个类方法来获取这些外部字段中的每一个(如果它们存在),或者如果它们不存在则为空白,但我也不确定这是否是最好的方法。

4

2 回答 2

3

让数据库为你做这件事。

使用一个交叉关系过滤器来获取所有A的 a bwith namewhich is not null

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

为此,当a.b为 None 时包含虚拟值,请使用以下命令:

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"



另外,作为旁注,不要以这种方式进行字符串连接——它的效率非常低,因为 Python 字符串是不可变的。以下要好得多:

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)



第二个注意事项:上面的代码将在 for 循环的每次迭代中执行查询以获取 ab。那可能会超级慢。考虑使用select_related一次性抓住所有东西。不过要小心 - 如果您的索引设置不正确,这也会很慢。启用此功能后,我会嗅探查询并花一些时间与您的查询计划器一起确保您没有进行任何令人讨厌的非索引查找。

修改后的代码:

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)
于 2012-04-10T22:42:43.840 回答
3

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

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

这使用了所有属性都存储在dict对象实际实例上的对象中的事实。您使用标准字典访问器get()来返回其中一个b或包含您感兴趣的属性的字典。这是一个糟糕的主意,但它确实存在。

此外,django/python 不是老式的 PHP。我不敢相信过去几周我在 stackoverflow 上看到了多少次,但是......不要连接字符串来生成 HTML!这就是模板语言的用途。用它。立即停止你正在做的事情。停止它停止它停止它。使用模板,不要尝试在视图中编写 HTML。这是一个可以证明是错误的事情,所以停下来。停下来。

于 2012-04-10T23:11:55.290 回答