Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django DB Models F Combined Expression

In [1]: from django.db.models import F

In [2]: from forum.models import Post

In [3]: post = Post.objects.get(id=1)

In [4]: post.view_count = F('view_count') + 1

In [5]: post.save()

In [6]: post.view_count

Out[6]: <CombinedExpression: F(view_count) + Value(1)>

In [7]: post = Post.objects.get(id=1)

In [8]: post.view_count

Out[8]: 3

After saved the post, it returned the combined expression.

I want the exact result (3).

is it possible to do without calling get method again / refresh_from_db ?

like image 660
Muthuvel Avatar asked Nov 12 '15 13:11

Muthuvel


People also ask

What is F in Django DB models?

F() expressions. 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.

What does F mean in Django?

In the Django QuerySet API, F() expressions are used to refer to model field values directly in the database.

Does Django ORM support subquery?

¶ Django allows using SQL subqueries.

Can Django models have functions?

Django's database functions represent functions that will run in the database. It provides a way for users to use functions provided by the underlying database as annotations, aggregations, or filters. Functions are also expressions, so they can be used and combined with other expressions like aggregate functions.


2 Answers

In Django 1.8+, you can use the refresh_from_db method. It won't save any SQL queries, but you might think the code is nicer.

>>> post = Post.objects.get(id=1)
>>> post.view_count
2
>>> post.view_count = F('view_count') + 1
>>> post.save()
>>> post.refresh_from_db()
>>> post.view_count
3

Since the update happens in the database, it's not possible to get the new value in Django without doing a get() or a refresh_from_db (which both cause a similar SQL query). However, it is possible to avoid the initial get() by using update() instead.

>>> Post.objects.filter(id=1).update(view_count=F('view_count') + 1)
>>> post = Post.objects.get(id=1)
>>> post.view_count
3
like image 192
Alasdair Avatar answered Oct 15 '22 11:10

Alasdair


From the docs https://docs.djangoproject.com/en/1.7/ref/models/queries/#f-expressions,

Python never gets to know about encapsulated SQL expression post.view_count = F('view_count') + 1 # F('view_count') Django sql expression.

it is dealt with entirely by the database.

So changes done on Database while Python all knows about the expression you applied rather then result.

You can do it by this way directly:-

post = Post.objects.filter(id=1)
post.update(view_count = F('view_count') + 1) 
like image 43
Vishnu Upadhyay Avatar answered Oct 15 '22 11:10

Vishnu Upadhyay