2012-12-29 21 views
17

Ben şu modellerDjango, tarih aralığında belirtilen ay ve yıl şeklinde filtre

class Destination_Deal(models.Model): 
    name = models.CharField(_("Nombre"),max_length=200) 

class Departure_Date(models.Model): 
    date_from= models.DateField(_('Desde'))  
    date_to= models.DateField(_('Hasta')) 
    destination_deal = models.ForeignKey(Destination_Deal,verbose_name = _("Oferta de Destino")) 

Bu tablo DEPARTURE_DATE gerçek veriler olduğunu

id date_from date_to  destination_deal_id 
1 2012-11-01 2013-03-17 1 
2 2012-11-01 2012-12-16 2 
3 2012-09-16 2012-10-31 3 
4 2012-11-01 2012-12-16 3 
5 2013-01-04 2013-01-11 4 

Ben eğer Destination_Deals filtrelemek istediğiniz Belirtilen bir ay & yılı date_from ile date_to arasındadır.

Örnek 1

Month: September (09)
Year: 2012

Aranan çıkış tarihleri ​​sonuç:
İD 3: 09/2012

Örnek 2

Month: February (02)
Year: 2013

dokunun yalnızca veri aralığı

Aranıyor çıkış tarihleri ​​sonucu:
ID 1: 03/2012

Yani, gün aslında is önemli değil önce 02/2012 olduğunu. & yılı, date_from ile date_to arasındaysa, bir gün olsa bile, filtre olmalıdır.

Sanırım this gibi bir şey kullanmalıyım ama nasıl yapacağımı bilmiyorum.

Şimdiden teşekkürler! Miguel

--- Düzen ---
Bu Aamir Adnan yanıt için test olmakla birlikte bunun Mart Kasım 2012 gider çünkü ID 1 de iade edilmelidir olarak beklendiği gibi çalışmıyor 2013, yani Ocak 2013 arasında.

Departure_Date.objects.all() 
[<Departure_Date: id: 1 - from: 2012-11-01 - to: 2013-03-17>, 
<Departure_Date: id: 2 - from: 2012-11-01 - to: 2012-12-16>, 
<Departure_Date: id: 3 - from: 2012-09-16 - to: 2012-10-31>, 
<Departure_Date: id: 4 - from: 2012-11-01 - to: 2012-12-16>, 
<Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>] 


month:1 
year:2013 
where = '%(year)s >= YEAR(date_from) AND %(month)s >= MONTH(date_from) \ 
    AND %(year)s <= YEAR(date_to) AND %(month)s <= MONTH(date_to)' % \ 
    {'year': year, 'month': month} 
Departure_Date.objects.extra(where=[where]) 
[<Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>] 

cevap

31

ara .extra kullanılarak documentation

year = 2012 
month = 09 
Departure_Date.objects.filter(date_from__year__gte=year, 
           date_from__month__gte=month, 
           date_to__year__lte=year, 
           date_to__month__lte=month) 

Alternatif bir yöntem:

where = '%(year)s >= YEAR(date_from) AND %(month)s >= MONTH(date_from) \ 
     AND %(year)s <= YEAR(date_to) AND %(month)s <= MONTH(date_to)' % \ 
     {'year': year, 'month': month} 
Departure_Date.objects.extra(where=[where]) 

terimi yukarısında, arzu edilen bir sonuç ortaya koymamıştır özel bir durum vardır. Örneğin

: ay 1 date_from içinde < ay 11 ama IF durum burada gereklidir MySQL böylece yıl farklı olduğu için

date_from='2012-11-01' 
date_to='2013-03-17' 
and input is 
year=2013 
month=1 

Sonra %(month)s >= MONTH(date_from) koşul yanlıştır: python kullanırken

where = '%(year)s >= YEAR(date_from) AND IF(%(year)s > YEAR(date_from), \ 
    IF(%(month)s > MONTH(date_from), %(month)s >= MONTH(date_from), %(month)s < MONTH(date_from)), \ 
    IF(%(month)s < MONTH(date_from), %(month)s < MONTH(date_from), %(month)s >= MONTH(date_from))) \ 
    AND %(year)s <= YEAR(date_to) \ 
    AND %(month)s <= MONTH(date_to)' % \ 
    {'year': year, 'month': month} 
Departure_Date.objects.extra(where=[where]) 
+3

: gibi bu işleri "FieldError:.? Sahadaki Üyelik arama türü için 'date_to' izin verilmez sen yanlış girdiniz 'ay'" AFAIK, ekleri karıştırmak mümkün değil mi ya da yanlış mıyım? –

+0

Bu garip, tarihteki genişletilmiş aramaları (ör. Yıl, ay) '__in' izinli olmadığını biliyorum. Lütfen cevabımdaki alternatif metodu kontrol edin. Teşekkürler –

+0

Şimdi "DatabaseError: (1064,") SQL sözdiziminizde bir hata var; 'MONTH (date_from)> = 12 YEAR (date_to) yakınında kullanmak için doğru sözdizimi için MySQL sunucu sürümünüze karşılık gelen kılavuzu kontrol edin <= 2012 AY (date_to) <= 12 LİMİT 21 'satır 1'de ")". Veritabanını bağımsız tutmak ve Departure_Date yerine Destination_Dates kullanmak için "ekstra" olmayan başka bir yol var mı? –

3

Çözüm sadece kod. Ana fikir, python ile date_from ve date_to oluşturmaktır.Sonra bu tarihler __lte ve __gte ile filter kullanılabilir: Artık

import calendar 
from datetime import datetime 
from django.db.models import Q 

def in_month_year(month, year): 
    d_fmt = "{0:>02}.{1:>02}.{2}" 
    date_from = datetime.strptime(
     d_fmt.format(1, month, year), '%d.%m.%Y').date() 
    last_day_of_month = calendar.monthrange(year, month)[1] 
    date_to = datetime.strptime(
     d_fmt.format(last_day_of_month, month, year), '%d.%m.%Y').date() 
    return Departure_Date.objects.filter(
     Q(date_from__gte=date_from, date_from__lte=date_to) 
     | 
     Q(date_from__lt=date_from, date_to__gte=date_from)) 

bu çalışacaktır:

>>> Departure_Date.objects.all() 
[<Departure_Date: id: 1 - from: 2012-11-01 - to: 2013-03-17>, 
<Departure_Date: id: 2 - from: 2012-11-01 - to: 2012-12-16>, 
<Departure_Date: id: 3 - from: 2012-09-16 - to: 2012-10-31>, 
<Departure_Date: id: 4 - from: 2012-11-01 - to: 2012-12-16>, 
<Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>] 


>>> in_month_year(month=1, year=2013) 
[<Departure_Date: id: 1 - from: 2012-11-01 - to: 2013-03-17>, 
<Departure_Date: id: 5 - from: 2013-01-04 - to: 2013-01-11>] 
+0

Çok teşekkürler. İşe yaradı. – Jay

0
Sen DateTimeField/date içinde hassasiyet eksikliğinden kaynaklanan "empedans uyumsuzluğu" sorunun üstesinden gelebilirsiniz

nesne karşılaştırması - aralığı aralığındaki bir datetime.timedelta kullanarak, aralıkta son tarihe bir gün eklemek için oluşabilir. Aşağıdaki hata var

import datetime 

start = date(2012, 12, 11) 
end = date(2012, 12, 18) 
new_end = end + datetime.timedelta(days=1) 

ExampleModel.objects.filter(some_datetime_field__range=[start, new_end]) 
İlgili konular