2012-12-29 15 views
17

I持って、次のモデルジャンゴ、日付範囲の指定された月と年によってフィルタ

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

これは、テーブルDEPARTURE_DATEの実際のデータである

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 

私は場合Destination_Dealsをフィルタリングしたいと思います指定された月の&年はdate_fromとdate_toの間です。

例1

Month: September (09)
Year: 2012

募集出発日付結果:
ID 3:それは09/2012

例2

Month: February (02)
Year: 2013

を触れるだけデータ範囲です

は、出発日が発生募集:
1 ID:02/2012だから03/2012

前に、日は実際には関係ありませんです。月&の年がdate_fromとdate_toの間にある場合、1日であってもフィルタでなければなりません。

私はthisのようなものを使用しなければならないと思いますが、どうすればよいか分かりません。

ありがとうございます! ミゲル

---編集---
これはアーミルアドナンからの応答のためのテストですが、それは2012年11月から月に行くので、ID 1をも返さなければならないので、私は期待どおりに動作しません2013年1月です

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>] 

答えて

31

.extraを用い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) 

別の方法を調べる:

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

クエリ上に所望の結果が得られない特定の場合があります。例えば

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

月1 date_fromで<月11ですが、MySQL IF条件がここで必要とされるように年が異なるため、その後%(month)s >= MONTH(date_from)条件が間違っている:

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

"FieldError:フィールド 'date_to'への参加が許可されていません。ルックアップタイプで 'month'のスペルを間違えましたか? AFAIK接尾辞を混ぜることはできないか、私は間違っていますか? –

+0

これは奇妙なことですが、日付に拡張された検索(例:年、月) '__in'は許可されていません。私の答えで代替方法を確認してください。ありがとうございました –

+0

"DatabaseError:(1064、" SQL構文にエラーがあります.MONTH(date_from)> = 12 YEAR(date_to)の近くで使用する正しい構文についてはMySQLサーバーのバージョンに対応するマニュアルをチェックしてください。 <= 2012 MONTH(date_to)<= 12 LIMIT 21 '1行目) ")。 Departure_Dateの代わりにDestination_Dealsを使用して、データベースを独立に保つために「余分」がなければ他の方法はありますか? –

3

ソリューションのpythonを使用してコードのみ。主なアイデアは、pythonでdate_fromとdate_toを構築することです。そして、これらの日付は__lte__gtefilterで使用することができます

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

さて、これは動作します:

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

ありがとうございます。出来た。 – Jay

0

あなたはDateTimeField/dateに精度不足による「インピーダンス不整合」を回避することができますオブジェクトの比較 - の範囲を使用する場合 - datetime.timedeltaを使用して範囲内の最後の日付を追加します。これは次のように動作します:

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]) 
関連する問題