I have a QuerySet with a prefetch_related() (with Prefetch object)
I want to see the raw query and print(qs.query) and it doesn't show anything about the prefetch_related stuff.
How do I see the query which will be run because of prefetch_related?
The queryset's query object will only show you the query that Django generates for the queryset itself (before any prefetch_related etc. is applied).
You probably need to look at these guidelines for inspecting the query that is actually sent to your database:
from django.db import connection
print(connection.queries)
Alternatively you can use something like django-debug-toolbar to display the queries.
Related
I have written this in django
a = Model.objects.all()
Will this query execute immediately or not?
When will this query fetch the request from the db?
In Django the Querysets are lazy i.e. when you create a queryset, it will involve any database activity,unless the queryset is evaluated.Read this Documentation for more in depth information.
Django 1.7
I have a model:
class Model(models.Model):
tags = models.ManyToManyField(..)
When I do Model.objects.prefetch_related().... it results in many individual queries being issued to fetch the tags, one for each model.
I'd expect 2 queries to happen: 1 to fetch the models, another to fetch the tags for all models.
How to do that?
EDITED:
I'm using a raw query like Model.objects.prefetch_related('tags').raw_query(..)
You should specify a field name to prefetch:
Model.objects.prefetch_related('tags')
If you use the queryset.raw() method then prefetch_related() logic doesn't work.
Given the following code:
progresses = Progress.objects.filter(customer=request.user).select_related()
if id is not None
progress = progresses.get(pk=id)
else:
progress = progresses[0]
Do I need to add select_related() to the second query such as progress = progresses.filter(pk=id).select_related()?
No, your progress queryset object already has the foreign key relationships included in the underlying sql. It's creating a select query with joins. Filtering it further won't remove the joins.
There's an example in the docs of further processing a query that includes select_related (though not using filter).
The order of filter() and select_related() chaining isn’t important.
These querysets are equivalent:
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())
From official Django docs: https://docs.djangoproject.com/en/1.9/ref/models/querysets/
I have a table 'Comments' and inside field the 'user', I would get in addition to the profile Profile in the same query. Currently I have something like that
comments = models.Comment.objects.select_related('author__profile').filter(post=article)
Unfortunately I can not retrieve information about profile, I can only get to it through
comment.author._profile_set_cache
Any ideas to make it look nice like?
comment.author.profile
If the 'author' is from the contrib.auth User model, then you don't have a FK to the UserProfile. It is a "reverse one-to-one". Fortunately, django is able to navigate a reverse one-to-one using "select_related", so the query is actually retrieving the fields (you can check it by using
print models.Comment.objects.select_related('author__profile').filter(post=article).query
The way to get the profile of a user is with the get_profile() method:
print comment.author.get_profile()
As the profile data is already cached (that's why the _profile_set_cache is for), getting the object means no additional query.
How do you view the SQL generated by Django for a DELETE?
When doing a SELECT operation on a query set, you can do this:
>>> qs = Entry.objects.filter(date__gt='2010-06-01')
>>> qs.query.as_sql()
('SELECT ...)
But I don't know how to get the SQL for what happens when I do qs.delete().
It looks a bit more involved because Django "emulates the behavior of the SQL constraint ON DELETE CASCADE" when deleting objects.
(Background: trying to debug an IntegrityError generated by a foreign key constraint when deleting a subclassed model object.)
This works well enough:
>>> from django.db import connection
>>> connection.queries[:-10]
Thought the exceptions occurred before the queries were added to connection.queries, but they are indeed present.
Here's another method which relies on Django internals and doesn't include queries to do cascading deletes, but doesn't require executing the query:
from django.db.models import sql
qs = Entry.objects.filter(date__gt='2010-06-01')
query = qs.query.clone()
query.__class__ = sql.DeleteQuery
print(query)
You could try running django-debug-toolbar and see the queries that way.