django - DeserializationError: ['“F(view_count) + Value(1)” value must be an integer.']
问题描述
我正在使用 Django 3.2
我正在使用 F 值来增加字段值(以避免潜在的竞争条件) -正如官方文档中所建议的那样。
这是我的代码片段(引发异常的部分):
def __update_fields(self, interaction_type):
if interaction_type == Engagement.VIEW:
self.view_count = F('view_count') + 1
#elif check which field needs updating ...
self.save() # By the time we get here, the necessary field (NOTE: **SINGULAR** word 'field') would have been updated
self.refresh_from_db()
我收到此错误:
DeserializationError: ['“F(view_count) + Value(1)” value must be an integer.']: (poll.poll:pk=10) field_value was 'F(view_count) + Value(1)'
这是完整的堆栈跟踪:
Internal Server Error: //path/to/example
Traceback (most recent call last):
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 1836, in to_python
return int(value)
ValueError: invalid literal for int() with base 10: 'F(view_count) + Value(1)'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/path/to/myproj/env/lib/python3.8/site-packages/django/core/serializers/python.py", line 144, in Deserializer
data[field.name] = field.to_python(field_value)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 1838, in to_python
raise exceptions.ValidationError(
django.core.exceptions.ValidationError: ['“F(view_count) + Value(1)” value must be an integer.']
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/path/to/myproj/env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/views/generic/detail.py", line 107, in get
context = self.get_context_data(object=self.object)
File "/path/to/myproj/poll/views.py", line 513, in get_context_data
poll.interact(self.request.user, Engagement.VIEW, self.request)
File "/path/to/myproj/social/models.py", line 988, in interact
self.__update_fields(interaction_type)
File "/path/to/myproj/social/models.py", line 947, in __update_fields
self.save()
File "/path/to/myproj/poll/models.py", line 97, in save
super().save(*args, **kwargs)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/base.py", line 726, in save
self.save_base(using=using, force_insert=force_insert,
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/base.py", line 774, in save_base
post_save.send(
File "/path/to/myproj/env/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 180, in send
return [
File "/path/to/myproj/env/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 181, in <listcomp>
(receiver, receiver(signal=self, sender=sender, **named))
File "/path/to/myproj/moderation/register.py", line 321, in post_save_handler
moderated_obj = ModeratedObject.objects.get_for_instance(instance)
File "/path/to/myproj/moderation/managers.py", line 73, in get_for_instance
moderated_object = self.get(object_pk=instance.pk,
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/query.py", line 431, in get
num = len(clone)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/query.py", line 262, in __len__
self._fetch_all()
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/query.py", line 69, in __iter__
obj = model_cls.from_db(db, init_list, row[model_fields_start:model_fields_end])
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/base.py", line 515, in from_db
new = cls(*values)
File "/path/to/myproj/moderation/models.py", line 66, in __init__
super().__init__(*args, **kwargs)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/db/models/base.py", line 505, in __init__
post_init.send(sender=cls, instance=self)
File "/path/to/myproj/env/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 180, in send
return [
File "/path/to/myproj/env/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 181, in <listcomp>
(receiver, receiver(signal=self, sender=sender, **named))
File "/path/to/myproj/moderation/fields.py", line 90, in post_init
self._deserialize(value))
File "/path/to/myproj/moderation/fields.py", line 54, in _deserialize
obj = next(obj_generator).object
File "/path/to/myproj/env/lib/python3.8/site-packages/djmoney/serializers.py", line 55, in Deserializer
for inner_obj in PythonDeserializer([obj], **options):
File "/path/to/myproj/env/lib/python3.8/site-packages/django/core/serializers/python.py", line 146, in Deserializer
raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value)
django.core.serializers.base.DeserializationError: ['“F(view_count) + Value(1)” value must be an integer.']: (poll.poll:pk=10) field_value was 'F(view_count) + Value(1)'
这个神秘错误的含义是什么(我传递的值 [1],显然是一个整数)。我该如何解决这个问题?
[[编辑]]
我在调试控制台中做了一些额外的调查,看看表达式实际返回了什么F('field_name') + 1
结果如下:
my_object.view_count # This is immediately after the assignment `F() + var`
<CombinedExpression: F(view_count) + Value(1)>
my_object.save() # Saving to see if exception thown (none thrown)
None
photo.view_count # Checking to see what on earth is stored in the field
<CombinedExpression
因此,似乎 django 文档是错误的,或者我误解了如何安全地增加字段值 - 直接在数据库中编写 SP 可能会更快,甚至编写一个线程安全类来处理这个 - 它真的不应该这么难做到这一点。
解决方案
将我的评论转换为答案以添加更多上下文。
view_count 的初始值是否可能不是整数?例如没有?
此外,从堆栈跟踪中,我看到在__update_fields
. 如果对那里的当前实例执行更多操作view_count
,则可能会因此而出现问题。基本上,如果以后使用相同的 python 实例,值view_count
将是。<CombinedExpression: F(view_count) + Value(1)>
保存后您可能需要从数据库中刷新实例。
推荐阅读
- java - 如何选择特定容器的跨度元素(由 CSS 类定义)使用 Xpath?
- flutter - 颤振滑块颜色
- assembly - 将数组 arg 的第一个值移动到 xmm0
- python-3.x - 我应该如何从 data-* 属性中抓取数据?
- java - 如何在java中调整二维数组的大小
- linkedin - LinkedIn 访问令牌 API 在 C# 中返回空值
- ruby-on-rails - Rails 出租电商平台
- google-analytics - 本地主机(127.0.0.1)应用程序上的 GTM Google 分析未被跟踪
- python - 'tuple' 对象不能解释为整数:两种代码解释有什么区别
- python - 这是一个类变量吗?