tgoop.com/djangolearn_ir/1103
Last Update:
وات ایز F() expressions در جنگو 😁
جنگو در مورد تابع 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.
Django uses the F() object to generate an SQL expression that describes the required operation at the database level.
آخرش چی گفته؟ database level
این تابع برای مواقعی به درد میخوره که ممکنه همزمانی یا Concurrency پیش بیاد.
مثلا یه جایی میخواییم از انبار یه محصول کم کنیم، همزمان یه ریکوئست دیگه میاد که اونم میخواد کم کنه.
حالت عادی و بدون استفاده از F ، چون آبجکت توی مموری اومده و مثلا مقدار انبار 10 هست، هر دو از آبجکت توی مموری کم میکنن،
لذا انبار 9 میشه 😳
ولی با F مستقیم آپدیت روی رکورد زده میشه.
پیچوندمش؟ 😅 یه مثال:
فرض کن یه مدل داریم:
class Product(models.Model):
name = models.CharField(max_length=100)
stock = models.IntegerField(default=0)
حالا بخوایم یه محصول رو یه دونه کم کنیم:
product = Product.objects.get(id=1)
product.stock = product.stock - 1
product.save()
مشکل:
اگر دو درخواست همزمان این کار رو بکنن، ممکنه هر دو یک مقدار قدیمی بخونن (مثلاً stock=10) و بعد از save، نتیجه بشه stock=9، در حالی که باید 8 میشد!
این همون مشکل همزمانی (Concurrency ) هست.
با F اینجوری میشه:
from django.db.models import F
Product.objects.filter(id=1).update(stock=F('stock') - 1)
اینجا F('stock') به دیتابیس میگه:
«به جای اینکه مقدار stock رو بیارم تو پایتون و دوباره بنویسم، مستقیماً در سطح دیتابیس مقدار فیلد رو یکی کم کن.»
این کار باعث میشه اتمیک (atomic) باشه و نیازی به lock دستی یا نگرانی از race condition نباشه.
راستی این lock باعث Deadlock نمیشه.
چون Deadlock وقتی پیش میاد که دو یا چند تراکنش همزمان قفل منابع مختلف رو بگیرن و هرکدوم منتظر آزاد شدن قفل اونوری بمونن.
BY جنگولرن
Share with your friend now:
tgoop.com/djangolearn_ir/1103
