الاستعلام عن القيم على أساس التاريخ ث/ django orm

StackOverflow https://stackoverflow.com/questions/1371280

  •  21-09-2019
  •  | 
  •  

سؤال

لدي مجموعة من الكائنات التي لها قيمة وحقل تاريخ:

obj1 = Obj(date='2009-8-20', value=10)
obj2 = Obj(date='2009-8-21', value=15)
obj3 = Obj(date='2009-8-23', value=8)

اريد هذا عاد:

[10, 15, 0, 8]

أو الأفضل من ذلك ، مجموع إجمالي المجموع حتى تلك النقطة:

[10, 25, 25, 33]

سيكون من الأفضل الحصول على هذه البيانات مباشرة من قاعدة البيانات ، لكن على خلاف ذلك ، يمكنني القيام بالتجمع بسهولة مع Forloop.

أنا أستخدم ORM Django وأيضًا Postgres

تعديل:

فقط لألاحظ أن مثالي لا يغطي سوى بضعة أيام ، ولكن في الممارسة العملية ، لدي المئات من الكائنات التي تغطي عقدين نمت مع مرور الوقت (وقت طويل جدا)

هل كانت مفيدة؟

المحلول

لم يتم اختبار هذا واحد ، لأنه من الألم قليلاً لإعداد جدول Django للاختبار مع:

from datetime import date, timedelta
# http://www.ianlewis.org/en/python-date-range-iterator
def datetimeRange(from_date, to_date=None):
    while to_date is None or from_date <= to_date:
        yield from_date
        from_date = from_date + timedelta(days = 1)

start = date(2009, 8, 20)
end = date(2009, 8, 23)
objects = Obj.objects.filter(date__gte=start)
objects = objects.filter(date__lte=end)

results = {}
for o in objects:
    results[o.date] = o.value

return [results.get(day, 0) for day in datetimeRange(start, end)]

هذا يتجنب تشغيل استعلام منفصل لكل يوم.

نصائح أخرى

result_list = []
for day in range(20,24):    
    result = Obj.objects.get(date=datetime(2009, 08, day))
    if result:
        result_list.append(result.value)
    else:
        result_list.append(0)
return result_list

إذا كان لديك أكثر من OBJ لكل تاريخ ، فستحتاج إلى التحقق من LEN (OBJ) وتكرارها في حال كان أكثر من 1.

إذا قمت بحلق من خلال OBJ.Objects.get 100 مرة ، فأنت تقوم باستعلامات SQL 100. obj.objects.filter ستعيد النتائج إلى استعلام واحد SQL ، ولكن يمكنك أيضًا تحديد جميع حقول النماذج. الطريقة الصحيحة للقيام بذلك هي استخدام OBJ.Objects.values_List ، والتي ستقوم بذلك باستخدام استعلام واحد ، وتحديد حقل "القيم" فقط.

start_date = date(2009, 8, 20)
end_date = date(2009, 8, 23)

objects = Obj.objects.filter(date__range=(start_date,end_date))
# values_list and 'value' aren't related. 'value' should be whatever field you're querying
val_list = objects.values_list('value',flat=True)
# val_list = [10, 15, 8]

للقيام بمجموع تشغيل Val_List ، يمكنك القيام بذلك (ليس من المؤكد أن هذه هي الطريقة الأكثر إثارة)

for i in xrange(len(val_list)):
    if i > 0:
        val_list[i] = val_list[i] + val_list[i-1]

# val_list = [10,25,33]

تحرير: إذا كنت بحاجة إلى حساب الأيام المفقودة ، فإن إجابة Glenn Maynard جيدة بالفعل ، على الرغم من أنني أفضل بناء جملة DICT ():

objects = Obj.objects.filter(date__range=(start_date,end_date)).values('date','value')
val_dict = dict((obj['date'],obj['value']) for obj in objects)
# I'm stealing datetimeRange from @Glenn Maynard
val_list = [val_dict.get(day, 0) for day in datetimeRange(start_date, end_date)]
# val_list = [10,15,0,8]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top