这是一个奇怪的问题,所以提前抱歉。我在Django Rest中有一个模型,如下所示:
class BaseModel(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Foo(BaseModel):
barId = models.ForeignKey(Bar, unique=False)
fizzId = models.ForeignKey(Fizz, unique=False)
buzzId = models.IntegerField(unique=False)
value = models.TextField()
我有一个ViewSet需要返回所有具有给定{request_barId,request_buzzId,lastUpdateDate}的Foo的列表。这非常简单,
foobar = Foo.objects.filter(
buzzId=request_buzzId,
modified_date__gt=request_lastUpdateDate,
barId=request_barId)
这就是问题。 buzzId的默认值是指定的buzzId需要覆盖的基本列表,替换基本列表上的实例。这就是我有点失落的地方。我有一个解决方案,但我觉得它不是特别优雅,并且有一种方法可以做到更清洁。这是我执行叠加的代码:
base_foobar = Foo.objects.filter(
buzzId=base_buzzId,
modified_date__gt=request_lastUpdateDate,
barId=request_barId).exclude(
fizzId__in=[o.fizzId for o in foobar])
result = foobar | base_foobar
这看起来真的很笨拙。有没有办法清理它?
编辑:为了澄清,让我们说元组{1,0,'01 -01-1970'}的列表代表基本集(buzzId:0),并返回包含fizzIds {1的对象列表, 2,3,10}。让我们说元组{1,1,'01 -01-1970'}表示一些buzzId对一组完整字符串的请求。如果我们说我们的buzzId为1(称之为扩充)与fizzIds {2,10,15,20}匹配Foos,那么我们的结果集应该看起来像
{ (base) 1, (augment) 2, (base) 3, (augment) 10, (augment) 15, (augment) 20 }
这清楚了吗?
答案 0 :(得分:0)
您可以使用Q
合并为一个语句:
result = (Foo.objects
.filter(
Q(
modified_date__gt=request_lastUpdateDate,
barId=request_barId
)
&
(
Q(buzzId=request_buzzId)
|
(
Q(buzzId=base_buzzId)
&
~Q(fizzId__in=[o.fizzId for o in foobar])
)
)
)
.order_by( '-buzzId' if request_buzzId < base_buzzId else 'buzzId')
)[0] # fetch first result only
另外,请在将来格式化您的所有代码。它不一定像我一样,但它肯定有助于阅读你的问题。