比较没有F Objects的Django中的两个字段

时间:2011-03-30 10:06:01

标签: python django

我是新来的,使用Web Apps&搜索引擎优化。 StackOverflow是学习Python和Python的好方法。 Django非常感谢社区。现在我的问题!

我有几个Django模型:

class Subscription(models.Model):
   hotel = models.ForeignKey("Hotel", related_name="subscriptions")
   tier = models.ForeignKey("Tier")
   enquiry_count = models.PositiveIntegerField(default=0)
   start_date = models.DateField(null=True, blank=True)
   end_date = models.DateField(null=True, blank=True)

class Tier(models.Model):
   name = models.CharField(max_length=32)
   enquiry_limit = models.PositiveIntegerField(default=0)

我还有一个酒店模型,我将在这里以非常简化的形式显示:

class Hotel(models.Model):
   name = models.CharField("Hotel Name", max_length=128)
   address = models.TextField("Address", blank=True)
   town = models.CharField(max_length=64)
   star = models.PositiveIntegerField(default=0, null=True, blank=True)    

每家酒店都需要订阅才能显示在我的搜索结果中。每个订阅都有一个具有特定enquiry_limit的层。 订阅在达到end_date或其enquiry_count达到最大值时用完。即达到其层级的enquiry_limit。

我找到了一种直接使用F Objects执行此操作的方法,并且在我的开发机器上运行良好的排除:

self.premium_hotels = Hotel.objects.select_related().exclude(
   Q(subscriptions__end_date__lte=datetime.date.today()) | Q(subscriptions__enquiry_count__gte=F('subscriptions__tier__enquiry_limit')))

这不适用于网站的实时版本,但是因为它运行的是Django 1.0。关于如何在没有F对象的情况下实现此查询的任何提示?

我意识到显而易见的解决方案是升级,但我们需要立即推出,我需要时间准备和在我们迁移到Django 1.3之前进行测试

提前致谢!

2 个答案:

答案 0 :(得分:0)

如果没有F对象,您将无法在一个步骤中执行查询,您自己的选择是在不查看enquiry_limit的情况下运行查询,并对列表进行后处理以删除那些已超出的酒店它

下面的代码应该有效。

hotels = Hotel.objects.select_related().exclude(
    Q(subscriptions__end_date__lte=datetime.date.today()))

self.premium_hotels = []
for h in hotels:
    for sub in h.subscriptions.filter(start_date__lte=datetime.now(), end_date__gte=datetime.now()):
        if sub.enquiry_count < sub.tier.enquiry_limit:
            self.premium_hotels.append(h)
            break

答案 1 :(得分:0)

在查询集上使用extra插入自定义SQL(请参阅where / tables):

http://docs.djangoproject.com/en/dev/ref/models/querysets/#extra

e.g。 (粗略 - 你需要在SQL中匹配表名等)


self.premium_hotels = Hotel.objects.select_related().exclude(
   Q(subscriptions__end_date__lte=datetime.date.today())).extra(tables=["myapp_tier"], where=['myapp_subscriptions.enquiry_count 

Best bet it to run your query locally - look at what SQL it generates, that use that to figure out what to put in your call to extra