Django cached queryset.last() возвращает объект None для объекта не None
Мой код:
@ttl_cache(maxsize=50, ttl=60 * 60)
def get_query_set():
return Model.objects.all().order_by('year')
def get_latest():
cached_qs = get_query_set()
try:
return cached_qs.last().year if len(cached_qs) > 0 else None
except AttributeError:
print('~~~~~~~~~~~~~~~~~')
print('CHECK CIRCLECI PROBLEM')
print(cached_qs)
print(cached_qs.last())
print(len(cached_qs))
for aa in cached_qs:
print(aa)
print(type(aa))
print(dir(aa))
print(hasattr(aa, 'year'))
try:
print(aa.year)
except Exception:
print('no attr for aa')
print(Model.objects.all().order_by('year'))
for aaa in Model.objects.all().order_by('year'):
print(aaa)
print(aaa.year)
print('~~~~~~~~~~~~~~~~~')
raise
Без try-except
я получаю (на get_latest()
)
AttributeError: 'NoneType' object has no attribute 'year'
Когда я ловлю исключение, он выводит:
~~~~~~~~~~~~~~~~~
CHECK CIRCLECI PROBLEM
<QuerySet [<Model: Model object (2)>]>
None
1
Model object (2)
<class 'path.models.model.Model'>
['DoesNotExist', 'Meta', 'MultipleObjectsReturned', '__class__', '__delattr__', ..., 'year']
True
2019
<QuerySet []>
~~~~~~~~~~~~~~~~~
Итак, мы видим, что
- this problem is reproducible only at CircleCI build sometimes (I don't know how to reproduce it at local machine)
- cached queryset is not empty
- length of cached queryset is 1
- queryset object is not
None
and has attributeyear
- value of
year
is 2019 - real object is already deleted at DB and does not exist (physically DB table is empty)
- non cached queryset is empty (because of ⑥)
Я предполагаю, что last()
пытается повторно получить объект из БД, даже если queryset кэширован (из-за ленивого поведения queryset?). Но я не понимаю, почему это происходит? И что я должен ожидать от вывода last()
?
Я пытался удалить объект Model из DB вручную после кэширования python queryset, но last()
метод работает как ожидалось и возвращает правильное значение.
Есть идеи?