【问题标题】:Django model operating on a queryset在查询集上运行的 Django 模型
【发布时间】:2013-11-01 15:42:37
【问题描述】:

我是 Django 新手,对 Python 也有一些了解。我正在尝试找到循环查询集并在每个模型上设置变量的惯用方式。基本上我的模型依赖于来自 api 的值,模型方法必须将它的一个属性乘以这个 api 值才能获得最新的正确值。

目前我正在视图中执行此操作并且它有效,但我不确定这是实现我想要的正确方法。我必须在别处复制这个循环。

有没有办法可以将循环逻辑封装到查询集方法中,以便在多个地方使用?

注意:我在每个模型实例上设置的变量只是一个常规属性,没有保存到 db。我只需要能够设置该变量,而不是保存它。

我有这个 atm(我正在使用 django-rest-framework):

class FooViewSet(viewsets.ModelViewSet):
    model = Foo
    serializer_class = FooSerializer

    bar = # some call to an api

    def get_queryset(self):
        # Dynamically set the bar variable on each instance!
        foos = Foo.objects.filter(baz__pk=1).order_by('date')
        for item in foos:
            item.needs_bar = self.bar

        return items

我认为这样会更好:

def get_queryset(self):
    bar = # some call to an api
    # Dynamically set the bar variable on each instance!
    return Foo.objects.filter(baz__pk=1).order_by('date').set_bar(bar)

我认为 api 命中应该在控制器中,然后注入到模型的实例中,但我不确定你是如何做到的。我一直在寻找查询集和管理器,但仍然无法弄清楚,也无法确定它是否是实现我想要的最佳方法。

谁能建议用 django 建模的正确方法?

谢谢。

【问题讨论】:

  • 不是重复的,至少不是那个问题。 OP 想要更新模型的内存实例,而不是数据库记录。
  • 我刚刚在提议的欺骗中测试了解决方案,但它不起作用:Item has no field named 'btc_usd' 该字段只是一个属性,不会保存到数据库中。
  • 因为 python 是笨拙的打字,你已经做对了。只要 need_bar 不是现有属性。
  • 在视图中这样做并没有错,但是如果您发现自己重复它,您可以将其封装在一个独立的函数中。我不会让它成为任何类的方法,除非它实际上依赖于该类来确定 bar 值。

标签: python django model-view-controller django-models django-rest-framework


【解决方案1】:

您可以在查询集项目上设置一些新属性,但它们不会更新数据库(将仅保存在本地命名空间中)。我想您想重新计算模型的字段,将其乘以某个值:

class Foo(models.Model):
     calculated_field = models.BigIntegerField(default=0)

def save(self, *args, **kwargs):
    if self.pk is not None:  # it's not a new record
       foo = kwargs.get('foo')
       if foo:
           self.calculated_field = self.calculated_field * int(foo)
    super(Foo, self).save(*args, **kwargs) # Call the "real" save() method.


 def get_queryset(self):
        bar = # some call to an api
        # Dynamically set the bar variable on each instance!
        foos = Foo.objects.filter(baz__pk=1).order_by('date')
        for item in foos:
            item.save(foo=bar)
       # return updated data
       return Foo.objects.filter(baz__pk=1).order_by('date')

如果您要同时运行此代码,有时您可能需要使用事务。

【讨论】:

  • 抱歉忘记添加字段只是模型上的属性 - 它没有保存到数据库中。我假设update 会命中我不需要的数据库。我只需要在方法中使用的每个模型上设置一个变量。
  • @nickzam - “你不能只在查询集项目上设置一些新属性”。当然可以,它们只是 Python 对象,就像其他任何东西一样。新属性不会保存到数据库中,但可以在内存中向它们添加任意值。
  • @Peter DeGlopper - 谢谢,你是对的。编辑了我的答案
猜你喜欢
  • 1970-01-01
  • 2012-12-15
  • 2010-09-26
  • 2017-11-22
  • 1970-01-01
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 2016-05-24
相关资源
最近更新 更多