2

Using Django's ORM, I am trying to find instances of myModel based on two of its datetime variables; specifically, where the months of these two datetimes are not equal. I understand to filter by the value of a modelfield, you can use Django's F( ) expressions, so I thought I'd try something like this:

myModel.objects.filter(fixed_date__month=F('closed_date__month'))

I know this wouldn't find instances where they aren't equal, but I thought it'd be a good first step since I've never used the F expressions before. However, it doesn't work as I thought it should. I expected it to give me a queryset of objects where the value of the fixed_date month was equal to the value of the closed_date month, but instead I get an error:

FieldError: Join on field 'closed_date' not permitted. Did you misspell 'month' for the lookup type?

I'm not sure if what I'm trying to do isn't possible or straightforward with the ORM, or if I'm just making a simple mistake.

4

2 回答 2

2

看起来 django F 对象目前不支持在 a 中提取月份DateTimeField,错误消息似乎表明 F 对象正在尝试将字符串 'closed_date__month' 中的 '__' 转换为Foreignkey不同对象之间的 a ,它们是通常作为连接存储在 sql 数据库中。

您可以通过遍历对象来执行相同的查询:

result = []
for obj in myModel.objects.all():
    if obj.fixed_date.month != obj.closed_date.month:
        result.append(obj)

或作为列表理解:

result = [obj for obj in myModel.objects.all() if obj.fixed_date.month != obj.closed_date.month]

或者,如果这不够有效,则可以将两个日期的月份缓存为IntegerFields模型中,例如:

 class myModel(models.Model):
     ....other fields....
     fixed_date = models.DateTimeField()
     closed_date = models.DateTimeField()
     fixed_month = models.IntegerField()
     closed_month = models.IntegerField()

更新相关日期时存储两个整数:

myModel.fixed_month = myModel.fixed_date.month
myModel.save()

然后使用一个 F 对象来比较两个整数字段:

myModel.objects.filter(fixed_month__ne=F('closed_month'))

修饰符将ne进行不相等测试。

编辑 - 使用原始 sql

如果您使用的是基于 sql 的数据库,那么最有效的方法是使用.raw()手动指定 sql 的方法:

myModel.objects.raw('SELECT * FROM stuff_mymodel WHERE MONTH(fixed_date) != MONTH(close_date)')

其中 'stuff_mymodel' 是数据库中表的正确名称。这使用 SQLMONTH()函数从月份字段中提取值,并比较它们的值。它将返回一个对象集合。

关于 django 查询系统有一些反对意见,例如:http ://charlesleifer.com/blog/shortcomings-in-the-django-orm-and-a-look-at-peewee-a-lightweight-alternative /。这个例子可以看作是在它的查询 api 中展示了另一个不一致的地方。

于 2013-11-13T20:28:06.903 回答
1

我的想法是这样的:

class myModel(models.Model):
    fixed_date = models.DateTimeField()
    closed_date = models.DateTimeField()

    def has_diff_months(self):
        if self.fixed_date.month != self.closed_date.month:
            return True
        return False

然后:

[x for x in myModel.objects.all() if x.has_diff_months()]

但是,要获得真正有效的解决方案,您必须使用另一列。对我来说,它是一个在您保存时创建的计算布尔字段,如下所示:

class myModel(models.Model):
    fixed_date = models.DateTimeField()
    closed_date = models.DateTimeField()
    diff_months = models.BooleanField()

    #overriding save method
    def save(self, *args, **kwargs):
        #calculating the value for diff_months
        self.diff_months = (self.fixed_date.month != self.closed_date.month)
        #aaand... saving:              
        super(Blog, self).save(*args, **kwargs)

然后过滤将只是:

myModel.objects.filter(diff_months=True)
于 2013-11-15T19:43:23.783 回答