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
精彩评论