Выражение Django F в выражении boolean вызывает исключение TypeError
Я использую Django 3.2 в проекте. У меня есть метод, который сравнивает значение поля с целым числом (см. код ниже).
Django выбрасывает ошибку (что имеет смысл из-за различных типов).
Мой вопрос в том, как еще я могу реализовать эту проверку (при этом используя выражение F, чтобы избежать условий гонки)?
Code
def bookmark(self, actor, note=''):
if self.can_bookmark(actor):
ct, object_id = self.get_content_info()
found_objects = self.bookmarks.filter(content_type=ct, object_id=object_id, actor=actor)
if found_objects:
# We are unbookmarking
found_objects.delete()
self.bookmarks_count = F('bookmarks_count') - 1
# Sanity check (-ve value may occur if Db has been manipulated manually for instance)
if self.bookmarks_count < 0: # <- Barfs here
self.bookmarks_count = 0
if self.bookmarks_count == 0: # <- Barfs here too
self.last_bookmarked = None
self.save()
return True
else:
# Create bookmark object and save it
if self.create_and_increment(self.bookmarks, actor, note=note):
self.bookmarks_count = F('bookmarks_count') + 1
self.last_bookmarked = timezone.now()
actionable_object = self.actionable_object
self.save()
self.refresh_from_db()
item_bookmarked.send(sender= actionable_object.__class__, instance=actionable_object, event_type = BOOKMARK, actor=actor)
return True
else:
return False
else:
# do nothing
return False
[[Edit]]
Вот полный отслеживание:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/path/to/myproj/models.py", line 455, in bookmark
if self.bookmarks_count < 0:
TypeError: '<' not supported between instances of 'CombinedExpression' and 'int'
Вы должны сначала выполнить проверку на вменяемость, или работать с Greatest
[Django-doc]:
from django.db.models import Value
from django.db.models.functions import Greatest
self.bookmarks_count = Greatest(F('bookmarks_count') - 1, Value(0))
self.save()
self.refresh_from_db(fields=('bookmarks_count',))
if self.bookmarks_count == 0:
self.last_bookmarked = None
self.save()
Здесь .refresh_from_db(…)
[Django-doc] обеспечит получение обновленных bookmarks_count
.
Note: You do not have to store the number of items of a
ManyToManyField
in another field. You can use.annotate(…)
[Django-doc] when you need to determine this by the database. Storing this explicitly in a field is a form of data duplication, and it turns out that keeping these in sync is harder than what one might expect.