Django Orm
Django ORM#
Recap#
Using the Course
model
All records in database#
Course.objects.all()
No records but an empty queryset#
Course.objects.none()
Get a single course#
Course.get()
or
get_object_or_404()
Creating records#
New Instance
Course.create()
Also returns the instance
Save existing
Course.save()
Queryset#
Queryset - collection of records returned from the database
- Anything that can return from a SQL query can be in a queryset
- They are lazy, they won’t do the work until it is needed - they are in memory and don’t hit the dtabase until they are consumed
User Model#
Useful but not required features are in django.dontrib
So from django.contrib.auth.models import User
Mass Update#
update()
can be called on a queryset but not a single record
models.Course.objects.update(published=True)
But that is the same as using all()
so we can use filter()
or exclude()
the same way
models.Course.objects.all().update(published=True)
Much better than using a loop
A delete()
can also be run on a querySet
Filter#
courses = models.objects.Course.filter(
teacher__username=teacher
)
What does the __
do?
It jumps from one relationship to another
Funny things like greater or equal to filter is:
reviews = models.Review.objects.filter(rating__gte = 3)
Instead of the intuitive
reviews = models.Review.objects.filter(rating >= 3)
More Info on field lookups
Blunk Create#
You have to pass bulk_create
an itereable that contains model instances that are not saved, eg.
Courses.objects.bulk_create([
Course(title=..., ...),
Course(..)
])
Only select the values you neeed#
Use values()
courses = Courses.objects.filter(published=True).values(‘id’, ‘title’)[:5]
Select just a single field from a bunch of record#
datetimes = Courses.objects.datetimes(‘created-at’, ‘year’)
Order By#
.order_by('-created_at')
created_at
is the field to order by, normally we do it in Ascending
order
Then -
makes it decending order
F Objects#
Allow you to refer to value in database not in instance which could be outdated
Use on sensitive data that has to be correct and real time, avoid race conditions
from django.db.models import F
Example
quiz.times_taken = F('times_taken') + 1
quiz.save()
So quiz.times_taken
becomes a CombinedExpression
quiz.refresh_from_db()
Can do a db update on live data with:
Course.objects.all().update(rating = F('rating') * 2)
Q objects#
Multiple conditions on Filter are ANDS#
When you add a filter:
.filter(
title__iconatins = 'red',
description_icontains = 'green'
)
It adds an AND
not an OR
You can also add multiple .filter().filter()
but then that will act as a chain
from django.db.models import Q
Q object filter
filter(
Q(title__icontains=title)|Q(description__icontains=term)
)
Q objects are sub-queries
|
makes it an OR
or UNION
Remember Q()
are non-keyword arguments **args
where as normal filters are keyword arguments **kwargs
Kwargs must always go after args
Searching is better to use a dedicated search engine like elasticsearch
Annotations#
Let django run operations on each item in a queryset and append the result of that as a new attribute
from django.db.models import Count, Sum
courses = models.course.objects.filter(
published=True
).annotate(
total_steps=Count('text',distinct(True)) + Count('quiz', distinct(True))
)
Aggregates#
total = courses.aggregate(total=Sum(total_steps))
Aggregates are done on qurysets
Prefetching and Seleting related#
prefetch_related
is for getting lots of other items, used if you want the reverse relationship - parent
to sub
Sometimes you can check the SQL debug toolbar to see any duplciate queries and extended time
try:
models.Course.objects.prefetch_related(
'quiz_set', 'text_set', 'quiz_set__question_set'
).get(pk=pk)
catch models.Course.DoesNotExist:
raise Http404
selected_related
is for smaller amounts of items (one)
The foreign key field, going from sub
to parent
step = models.Quiz.objects.select_related('course').get(
course_id=course_pk, pk=step.pk, course__published=True
)
These can make some huge performance improvements on SQL side
Testing ORM#
You can use the assertNumQueries
assertion to ensure that a certain number are queries are called