首页 > 其他分享 >F() expressions Django中解决数据竞态条件

F() expressions Django中解决数据竞态条件

时间:2023-01-05 17:12:55浏览次数:48  
标签:database reporter value Django field stories filed 竞态 expressions

class F¶
An F() object represents the value of a model field, transformed value of a model field, or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.

Instead, Django uses the F() object to generate an SQL expression that describes the required operation at the database level.

Let’s try this with an example. Normally, one might do something like this:

# Tintin filed a news story!
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()

Here, we have pulled the value of reporter.stories_filed from the database into memory and manipulated it using familiar Python operators, and then saved the object back to the database. But instead we could also have done:

from django.db.models import F

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

Although reporter.stories_filed = F('stories_filed') + 1 looks like a normal Python assignment of value to an instance attribute, in fact it’s an SQL construct describing an operation on the database.

When Django encounters an instance of F(), it overrides the standard Python operators to create an encapsulated SQL expression; in this case, one which instructs the database to increment the database field represented by reporter.stories_filed.

Whatever value is or was on reporter.stories_filed, Python never gets to know about it - it is dealt with entirely by the database. All Python does, through Django’s F() class, is create the SQL syntax to refer to the field and describe the operation.

To access the new value saved this way, the object must be reloaded:

reporter = Reporters.objects.get(pk=reporter.pk)
# Or, more succinctly:
reporter.refresh_from_db()

As well as being used in operations on single instances as above, F() can be used on QuerySets of object instances, with update(). This reduces the two queries we were using above - the get() and the save() - to just one:

reporter = Reporters.objects.filter(name='Tintin')
reporter.update(stories_filed=F('stories_filed') + 1)

We can also use update() to increment the field value on multiple objects - which could be very much faster than pulling them all into Python from the database, looping over them, incrementing the field value of each one, and saving each one back to the database:

Reporter.objects.update(stories_filed=F('stories_filed') + 1)

F() therefore can offer performance advantages by:

getting the database, rather than Python, to do work
reducing the number of queries some operations require
Avoiding race conditions using F()¶
Another useful benefit of F() is that having the database - rather than Python - update a field’s value avoids a race condition.

If two Python threads execute the code in the first example above, one thread could retrieve, increment, and save a field’s value after the other has retrieved it from the database. The value that the second thread saves will be based on the original value; the work of the first thread will be lost.

If the database is responsible for updating the field, the process is more robust: it will only ever update the field based on the value of the field in the database when the save() or update() is executed, rather than based on its value when the instance was retrieved.

标签:database,reporter,value,Django,field,stories,filed,竞态,expressions
From: https://www.cnblogs.com/ukzq/p/17028148.html

相关文章

  • Django-restframework 视图类
    HTTP请求响应drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作。所以在Django原有的django.views.View类基础上,drf封装了多个视图子类供我们使用。Django-r......
  • Django报错No module named django.core.urlresolvers
    当需要测试django能否解析网站根路径的URL,并将其对应到我们编写的某个视图函数上时,使用下面的语句fromdjango.core.urlresolversimportresolve执行代码时出现错误......
  • django-重要 节点梳理
    视图继承关系图:  模型类和管理器继承关系图:序列器化关系图: ......
  • django框架:django中间件
    django中间件官方说法:中间件是一个用来处理django的请求和响应的框架级别的钩子。说的直白一点中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,他本......
  • Django-restframework 序列化器与反序列化器
    序列化器restframework中提供了所有可用的序列化器基类,引用方法如下:fromrest_frameworkimportserializersSerializer:序列化器基类,drf中所有的序列化器都必须继承于S......
  • django时区问题的解决
    django时区问题的解决 更新时间:2021年05月18日09:37:58 作者:Silent丿丶黑羽  我们都知道时区,标准时区是UTC时区,django默认使用的就是UTC时区,我们希望存储在数据......
  • Django 03
    https://docs.djangoproject.com/en/4.1/intro/tutorial03/fromdjango.urlsimportpathfrom.importviewsapp_name='polls'urlpatterns=[path('',views.......
  • django 如何提升性能(高并发)
    django如何提升性能(高并发)对一个后端开发程序员来说,提升性能指标主要有两个一个是并发数,另一个是响应时间网站性能的优化一般包括web前端性能优化,应用服务器性能优化,存......
  • django中间件补充、django操作cookie与session
    django中间件补充、django操作cookie与session目录django中间件补充、django操作cookie与session基于django中间件实现功能的插拔式设计cookie与session简介django操作coo......
  • 问题:django.template.exceptions.TemplateSyntaxError: 'staticfiles' is not a regis
     django使用swagger自动生成API文档时,报错  解决方法: 在settings.py里面配置一下以下代码'libraries':{'staticfiles':'django.templatetags.static'......