Агрегация Джанго по диапазону дат - PullRequest
2 голосов
/ 23 мая 2010

Я скрываюсь и учусь здесь некоторое время. Теперь у меня есть проблема, которая почему-то не может найти легкое решение. Чтобы изучить django, я создаю приложение, которое в основном отслеживает забронированные предметы. Я хотел бы показать, сколько дней в месяце для выбранного года было забронировано одно изделие.

У меня есть следующие модели:

Asset(Model)

BookedAsset(Model):
 asset = models.ForeignKey(Asset)
 startdate = models.DateField()
 enddate = models.DateField()

Таким образом, имея следующие записи:

asset 1, 2010-02-11, 2010-02-13
asset 2, 2010-03-12, 2010-03-14
asset 1, 2010-04-30, 2010-05-01

Я хотел бы получить следующее:

asset 1    asset 2
-------    -------
Jan = 0    Jan = 0
Feb = 2    Feb = 0
Mar = 0    Mar = 2
Apr = 1    Apr = 0
May = 1    May = 0
Jun = 0    Jun = 0
Jul = 0    Jul = 0
Aug = 0    Aug = 0
Sep = 0    Sep = 0
Oct = 0    Oct = 0
Nov = 0    Nov = 0
Dec = 0    Dec = 0

Я знаю, что мне нужно сначала получить количество дней в диапазоне дат (и отслеживать, выпадают ли они из текущего месяца и в следующий месяц), а затем составить общее число дней. Я просто застрял на том, как сделать это элегантно в Джанго.

Любая помощь (или подсказка в правильном направлении) очень ценится.

Ответы [ 4 ]

0 голосов
/ 21 сентября 2012

Есть еще одно решение, которое делает это через представление базы данных и отображает это представление в модель django, используя параметр мета-класса managed = False

Подробные объяснения здесь: http://anthony -tresontani.github.com / Django / 2012/09/12 / wka-django-orm -ограничения /

0 голосов
/ 30 мая 2010

В конце я выбрал пользовательский запрос в качестве решения моего вопроса:

cursor = connection.cursor()
cursor.execute("""select to_char(allmonths.yeardate::date, 'YYYY/MM/DD') as monthdate,
                    COUNT("day") as bookings
                    from (
                    select distinct date_trunc('month', (date %s - offs)) as yeardate 
                    from generate_series(0,365,28) as offs
                    ) as allmonths
                    left join bookings_bookedassetday 
                    on EXTRACT(MONTH from "day")=EXTRACT(MONTH from yeardate) 
                    and asset_id=%s and EXTRACT(YEAR from "day") = %s
                    group by allmonths.yeardate
                    order by allmonths.yeardate asc""", [year+'-12-31', id, year])

query = cursor.fetchall()

Возможно, это не самый джангоистский способ сделать это, но я нашел это намного проще, чем понять это с помощью чистого джанго: |

Если у кого-то есть лучшая альтернатива, я весь в ушах:)

0 голосов
/ 24 июля 2010

Я бы не стал использовать ни один из приведенных выше ответов (даже если бы мне нравилось пробивать некоторый пользовательский SQL, но я не делал этого по крайней мере 5 лет), и ваша модель достаточно проста, чтобы ее можно было использовать в реляционной парадигме. 1001 *

Ответ, который вы ищете, - это функция annotate () в функции агрегирования django: http://docs.djangoproject.com/en/dev/topics/db/aggregation/ Единственное, что вам нужно знать, это как узнать дату на месяц, что объясняется в документации набора запросов: http://docs.djangoproject.com/en/dev/ref/models/querysets/#month

Грубый пример получения одного актива:

BookedAsset.objects.filter(asset=asset).annotate(month_count=Count('startdate__month')).order_by('startdate__month')

(очевидно, это неправильно, но я не мог не пересоздать вашу структуру, чтобы дать вам точное правильное утверждение, немного покопаться и прочитать документацию)

Вероятно, вы могли бы использовать все ресурсы за один раз, используя синтаксис объединения в тех же документах.

0 голосов
/ 23 мая 2010

Я не могу придумать способ сделать это с имеющейся у вас структурой модели.

Это довольно сложное требование, и, тем не менее, вы решите, что, вероятно, потребуется довольно много пользовательских SQL. Я думаю, что для начала вам может потребоваться изменить структуру, чтобы у вас была таблица BookedAssetDay, которая представляет каждый день отдельно для бронирования.

class BookedAsset(models.Model):
    asset = models.ForeignKey(Asset)
    day = models.DateField()

Тогда запрос выглядит примерно так:

BookedAsset.objects.extra(
    select={'month': 'MONTH(day)'}
).values('asset', 'month').annotate(Count('bookedasset__month'))
...