开发者

Compare two fields in Django without F Objects

I'm new here, working with Web Apps & SEO. StackOverflow has been a great resource in learning my way around Python & Django so a big thank you to the community. Now for my Question!

I have a couple of Django models:

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)

and:

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

I also have a Hotel Model that i'll show here in a very simlified form:

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)    

Each Hotel needs to have subscription to appear in my search results. Each Subscription has a Tier with a certain enquiry_limit. A subscription runs out when it either reaches the end_date OR its enquiry_count maxes out. i.e. Reaches 开发者_运维技巧the enquiry_limit of its tier.

I found a straightforward way of doing this with F Objects and an exclude which works nicely on my dev machine:

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')))

This will not work on the live version of the site however as it is running Django 1.0. Any tips on how to achieve this query without F objects?

I realize that the obvious solution is to upgrade but we need this rolled out right away and I'll need time to prepare & test before we move to Django 1.3

Thanks in advance!


Without F objects you will not be able to do the query in a single step, your own option is to run the query without looking at the enquiry_limit and the post process the list to remove those hotels which have exceeded it.

Something like the code below should work.

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


Use extra on the queryset to insert custom SQL (see where / tables):

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

e.g. (roughly - you'll need to match tables name etc in 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜