【问题标题】:Django how to select multiple columns on a single model instanceDjango如何在单个模型实例上选择多个列
【发布时间】:2013-09-19 04:55:49
【问题描述】:

这看起来很简单,但我忽略了,但不管怎样。

我定义了一个模型,我想从模型中检索某些列(不是通过 QuerySet API/模型管理器),而是在模型类中。

例子:

class mymodel(models.Model):
    col1 = ...
    col2 = ...
    col3 = ...

def __unicode__(self):
    return '%s %s' % (self.col1, self.col3) # Notice I'm omitting col2.

__unicode__ 类方法中,这至少算作2 个数据库查询。如何仅在 1 个 DB 查询中检索此类方法中的 col1 和 col3?好像应该这么简单,我觉得我在做一些愚蠢的事情。

更新:

根据反馈,我创建了一个测试模型、测试表格等……发现几位用户所说的都是正确的。但是,在我的 实际 代码中(使用多个表单),更改 __unicode__ 方法以返回一列连接值将 SQL 查询的数量从 601 更改为 34。我只更改了那一行.根据我的测试用例,可能发生了其他事情,但重申一下,我只更改了 unicode 方法,我得到的 DB 命中数量完全不同。

我不确定我的其他代码发生了什么,我将不得不尝试仔细查看它。同时这里是测试用例,证明你们是正确的:

# Models.py
class TestModelFK(models.Model):
    col1    = models.CharField(max_length=8)
    col2    = models.CharField(max_length=8)
    col3    = models.CharField(max_length=8)
    col4    = models.CharField(max_length=8)
    allcols = models.CharField(max_length=32, blank=True, editable=False)    

    class Meta:
        ordering        = ('col1', 'col2')

    def __unicode__(self):
        return '%s %s %s %s' % (self.col1, self.col2, self.col3, self.col4)

    def save(self, *args, **kwargs):
        self.allcols    = '%s %s %s %s' % (self.col1, self.col2, self.col3, self.col4)

        super(TestModelFK, self).save()

class TestModel(models.Model):
    quantity    = models.IntegerField()
    test_fk     = models.ForeignKey(TestModelFK)


# forms.py
class TestModelForm(forms.ModelForm):
class Meta:
    model = TestModel


# views.py
if request.method == 'GET':
    post['TestModelFormSet'] = formset_factory(TestModelForm, extra=4)

【问题讨论】:

  • -1 因为前提完全是错误的。
  • 你应该总是从__unicode__返回一个unicode对象而不是一个字符串。

标签: django model


【解决方案1】:

让我们看看你的函数:

def __unicode__(self):
    return '%s %s' % (self.col1, self.col3) # Notice I'm omitting col2.

当您调用__unicode__ 时,您的模型已经在内存中了。您可以根据需要访问来自self 的字段,此时没有数据库访问权限。

【讨论】:

    【解决方案2】:

    __unicode__ 方法调用是作为内存调用发生的。它不会触发单独的数据库调用。

    【讨论】:

      【解决方案3】:

      我猜你正在这样做

      myModelInstance = MyModel.objects().get(id=1)
      

      然后

      print myModelInstance
      >> "WhateverCol1is WhateverCol2is"
      

      这绝对会触发 1 个数据库调用,因为您必须获取该模型实例。 这就是get() 所做的,它会立即获取对象。

      由于您省略了字段声明,我猜测 col1col3 要么是 ManyToMany 字段要么是 ForeignKey,因此在获取实例时,它将获取字段所在的行参考。

      如果你有一个这样完成的查询集

      myModelInstances = MyModel.objects().filter(id=1)
      

      并对其进行迭代,它将评估它并需要 n 个数据库调用。

      QuerySet 是惰性的,只有在某些事情发生时才进行评估(即进入数据库),这些事情是

      • 遍历查询集
      • 对查询集进行切片
      • 在查询集上使用list()
      • 使用len()
      • 使用repr()
      • 酸洗或缓存 QuerySet

      阅读更多关于QuerySet here

      【讨论】:

      • 抱歉让你猜到了。在我得到一些反馈之前,我没有所有的信息。但总的来说,我是通过模型表单中的选择字段调用__unicode__ 方法。如果您看到我的其他 cmets,我不确定为什么要观察我所看到的行为,因为我的测试用例无法重现我的实际代码所展示的问题。
      猜你喜欢
      • 2020-04-17
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 1970-01-01
      • 2011-03-15
      • 2021-12-24
      • 1970-01-01
      相关资源
      最近更新 更多