2013-07-23 3 views
1

У меня есть следующие модели:Джанго фильтр внешнего ключа от даты бронирования

class House(models.Model): 
    Name = models.CharField(max_length=200, unique=True) 
    Reference = models.CharField(max_length=50, unique=True) 

class Booking(models.Model): 
    House = models.ForeignKey(House, related_name='booking') 
    InitialDate = models.DateField() 
    FinalDate= models.DateField() 

Теперь я хочу, чтобы выполнить запрос, чтобы отфильтровать все доступные дома для диапазона дат (например: 2013-07-21 к 2013-07-30), поэтому он должен исключать все дома с бронированием, начинающимся и заканчивающимся между этими двумя датами. Я мог бы выполнить этот запрос с помощью raw SQL, но без синтаксиса django.

Не могли бы вы помочь?

Большое спасибо!

+0

Какой необработанный SQL вы использовали? – falsetru

ответ

0

Предполагая, что период вы говорите между startdate и enddate, что эту работу:

booked = set([x.House.Reference for x in \ 
    Booking.objects.filter(InitialDate__lte=enddate).filter(FinalDate__gte=startdate)]) 
available = House.objects.exclude(Reference__in=booked) 
+0

Не могли бы вы объяснить свой код? Я не понимаю эту строку: reserved = set ([x.House.Reference for x in \ –

+0

) Возвращает набор (т. Е. Не повторяющихся записей) всех ссылок на дом, для которых существуют заказы между указанными датами. \ является символом продолжения, поэтому эта строка продолжается с 'Booking.objects ...'. – richsilv

0

Это можно непосредственно отфильтровывать благодаря обратной связи, созданного Django:

bookedHouses = House.objects.filter(booking__InitialDate__lte=enddate)\ .filter(booking__FinalDate__gte=startdate)

3

Я принял свободу использовать более питонический корпус.

class House(models.Model): 
    name = models.CharField(max_length=200, unique=True) 
    reference = models.CharField(max_length=50, unique=True) 

class Booking(models.Model): 
    house = models.ForeignKey(House, related_name='booking') 
    initial_date = models.DateField() 
    final_date= models.DateField() 

import datetime 
start_date = datetime.datetime(2013, 07, 21) 
end_date = datetime.datetime(2013, 07, 30) 

# so simply intersect 
booked = set(values['house_id'] for values in Booking.objects.objects.filter(
    initial_date__lte=end_date, final_date__gte=start_date).values('house_id')) 

House.objects.exclude(id__in=booked) 

thanx to richsilv для заданной идеи, логично, но я задумался об этом, прочитав его ответ. Он просто сводит инструкцию sql только с помощью отдельных домов.

+0

Огромное спасибо вам всем! Работает сейчас! Отличные ответы на все! –

3

При использовании Django ORM один из используемых методов заключается в том, что вы всегда должны начинать с отношений, которые вы хотите получить, в вашем случае House.

Я считаю, что это будет ваш путь идти о нем тогда:

unbooked_houses = House.objects.exclude(
    booking__InitialDate__gte=start_date, booking_FinalDate__lte=end_date) 

Таким образом, вы будете в конечном итоге с QuerySet и не нужно возиться с списковых и этажерки.

Кроме того, Python PEP-8 документ диктует, что вы должны следовать следующему правилу именования переменных и свойств:

Вместо InitialDate она должна быть предпочтительно initial_date.

+0

закрывающая скобка. – christophe31

+0

Спасибо, вы могли бы отредактировать ее для меня ! :) –

+0

это хороший ответ. – christophe31

Смежные вопросы