使用Django的ORM,我试图根据两个日期时间变量找到myModel的实例;具体而言,这两个日期的月份不相等。我理解过滤一个modelfield的值,你可以使用Django的F( ) expressions,所以我想我会尝试这样的事情:
myModel.objects.filter(fixed_date__month=F('closed_date__month'))
我知道这不会发现它们不相等的情况,但我认为这是一个很好的第一步,因为我之前从未使用过F表达式。但是,它并没有像我想象的那样有效。我希望它能给我一个对象的查询集,其中fixed_date
月的值等于closed_date
月的值,但我得到一个错误:
FieldError: Join on field 'closed_date' not permitted. Did you misspell 'month' for the lookup type?
我不确定我尝试做的事情是不可能的,也不是简单的ORM,或者我只是犯了一个简单的错误。
答案 0 :(得分:2)
看起来django F对象目前不支持在DateTimeField
内提取月份,错误消息似乎表明F对象正在尝试转换字符串'closed_date__month'中的'__'作为不同对象之间的Foreignkey
,通常作为连接存储在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'是数据库中表的正确名称。这使用SQL MONTH()
函数从月份字段中提取值,并比较它们的值。它将返回一组对象。
有关django查询系统的一些说法,例如:http://charlesleifer.com/blog/shortcomings-in-the-django-orm-and-a-look-at-peewee-a-lightweight-alternative/。这个例子可以用来证明它的查询api中的另一个不一致。
答案 1 :(得分: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)