Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django F expressions joined field

Tags:

python

sql

django

So I am trying to update my model by running the following:

FooBar.objects.filter(something=True).update(foobar=F('foo__bar')) 

but I get the following error:

FieldError: Joined field references are not permitted in this query 

if this is not allowed with F expressions...how can I achieve this update?

ticket

given the information in this ticket, I now understand that this is impossible and will never be implemented in django, but is there any way to achieve this update? maybe with some work around? I do not want to use a loop because there are over 10 million FooBar objects, so SQL is much faster than python.

like image 357
Ryan Saxe Avatar asked Jan 29 '14 18:01

Ryan Saxe


People also ask

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.

What is F in Django QuerySet?

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 is OuterRef?

OuterRef: It acts like an F expression except that the check to see if it refers to a valid field isn't made until the outer queryset is resolved. I am experiencing an issue with this using the following example: class ExampleModel(models.Model): date = models.DateField()

What is Select_related in Django?

Django offers a QuerySet method called select_related() that allows you to retrieve related objects for one-to-many relationships. This translates to a single, more complex QuerySet, but you avoid additional queries when accessing the related objects. The select_related method is for ForeignKey and OneToOne fields.


2 Answers

Django 1.11 adds supports for subqueries. You should be able to do:

from django.db.models import Subquery, OuterRef  FooBar.objects.filter(something=True).update(     foobar=Subquery(FooBar.objects.filter(pk=OuterRef('pk')).values('foo__bar')[:1]) ) 
like image 50
Georgi Yanchev Avatar answered Sep 21 '22 16:09

Georgi Yanchev


Why don't use raw sql here: Based on this, it will be something like

from django.db import connection  raw_query = ''' update app_foobar set app_foobar.foobar =  (select app_foo.bar from app_foo where app_foo.id = app_foobar.foo_id)  where app_foobar.something = 1;  '''  cursor = connection.cursor() cursor.execute(raw_query) 
like image 39
eran Avatar answered Sep 20 '22 16:09

eran