Part 7 - Queries in Django

November 20th, 2020 8 min read

This is part of the series Django For Beginners we are going to see about apps in app and we will see about models in django in this part.

In this post we are going to learn a lot queries in django. I recommend you to read last post so as it will be easy to understand context of this post , now let’s get started.

These are the models which we are going to use for most part in this post,

from django.db import models
from django.utils import timezone
from djnago.contrib.auth.models import User

class Post(models.Model)
	title = models.CharField(max_length=250)
	created_at = models.DateTimeField(
	author = models.ForeignKey('Author', on_delete=models.CASCADE, related_name="author")
	likes =  models.ManyToManyField(User, blank=True, related_name="likes")
	dislikes =  models.ManyToManyField(User, blank=True, related_name="dislikes")
	likes_count = models.PositiveIntegerField(default=0)
	dislikes_count = models.PositiveIntegerField(default=0)
	rating = models.DecimalField(max_digits=4, decimal_places=2)

class Author(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
	liked_posts = models.ManyToManyField(Post, blank=True, related_name="liked_posts")
	disliked_posts = models.ManyToManyField(Post, blank=True, related_name="disliked_posts")

If you understand all about models then head on to the query section by clicking here.

Models Explanations

Now let me explain what have I done above,

I have created 2 models, Post and Author , and we have added many fields to it, let’s see them one by one,

likes , dislikes , liked_books, disliked_books : I have merged because they have save field that is Many To Many Field it is used to create many to many relationship.

created_at : It is a datetime field and it used to store date and time in database. I have set it default value to so as to get current time and date and store it, the same could be achieved by using auto_now=True but it does not give flexibility to us.

author: It is a ForeignKey and is used to denote One to Many Relationship. The model is its first argument but as you may have seen I passed the first value as name of the model that is because as model is below that model it cannot find it as python interprets code line by line. So to solve this problem we pass name of model as a argument and it works thanks to django.

likes_count , dislikes_count : They use PositiveIntegerField it is same as IntegerField somewhat but it only supports values from 0 to 922337203685477580 while IntegerField supports values from from -2147483648 to 2147483647. Most of times PositiveIntegerField get’s the work and works for validation to o I like to use it more above IntegerField unless I need support for negative values.

user : It is an OneToOneField and is used to create one to one relationship , what is essentially means that the model passed to it as an argument will only have one model with the model to whose field is as OneToOneField.

title : It is a CharField and is used to store simple character data.

If you don’t know know about models I suggest you take a read about Models in django at 👨‍💻 Django For Beginners - Models in Django ( Part 5 ). It will definitely help you.

Yay Queries !

Finally we are going to see about queries in django, I am going to import all models at once and not again and again so keep his in mind if you are going to try these quries on you computer.

from .models import Post, Author

Get All

To get all data of the model we use this query, it is not used most often as it costs a lot of resources if data is large and it is always a good practice to limit the query results which we will see how to do after this,

all_posts = Post.objects.all()

syntax = ModelName.objects.all()

Limit Query Results

To limit results of any query we add [ start_count : end_count ] to get results from start_count and end_count you can also use [ : end_count ] to get results from 0 to end_count. Let’s see an example,

only_five_posts = Post.objects.all()[:4]

The above query will give 5 results only as index start from 0 and till 4 it would be five results.

Get Query

There is situation many times when we want to retrieve only one result from the query with exact match of fields for such situations we use get query, let me show you an example,

one_post = Post.objects.get(id=1)

syntax = ModelName.objects.get( pass_keyword_arguments )

Getting Many Search Results

Above we have seen how to retrieve one result but you can also search for exact filed value to obtain more than one result, let’s see an example,

one_post = Post.objects.filter(likes_count=10)

For such situations we use filter method.

syntax = ModelName.objects.filter( pass_keyword_arguments )

Getting Like Query Search Results

To obtain results let’s say for search we cannot use exact match as to provide better results so for such time we use LIKE Query in SQL and to use the same in django we use either __contains or __icontains, let me show you how ,

posts = Post.objects.filter(title__contains="The Title Not Exact")
posts = Post.objects.filter(title__icontains="The Title Not Exact")

To use LIKE query on a filed we add __contains or __icontains to its end as you can see above and then continue it.

Now you may ask what is difference between __contains and __icontains , it is not much just the difference is that __contains search results for same case on the field, whereas __icontains search results irrespective of case on the field.

Filtering by Date And Time

Using Date

You can also filters posts by date using this syntax by year created_at_date__year=2006 , you can also use by using datetime module more than or equal to ( >= ) Query , this format created_at_date__lte='2006-01-01' which creates less_than or equal to ( <= ) Query .

posts = Post.objects.filter(``)

Filtering by Foreign Key

We can also use foreign key to filter objects we can, let’s see an example, let’s us filter posts by author and then retrieve it all,

author = Author.objects.get(id=1)
posts  = Post.objects.filter(author=author)

It will get author of id 1 and then we have filtered posts, by passing query where author variable equals to author filed in the Post model. Under the hood django will gets author id and then queries post table where author of post equals to the id of the author object we have passed. In database foreign keys are store as integer values which are ids of the related author model.

Filtering by Many To Many Field

Many to many filed is a bit different then the fields than the other fields we have seen till now as it is not a filed instead it is a table itself. It has two fields which are ids of the related models in two tables.

Let’s understand it by an example,

First let’s understand how to create a entry in many to many field in django. It is very simple to do,

some_author = Author.objects.get(id=50)
some_post   = Post.objects.get(id=50)

This will do the thing the syntax is kind of like this model.many_to_many_field.add(related_model), and even if the many to many field has related_model already created it will not throw any error and will work fine, the same applies when we remove object from many to many field.

some_author = Author.objects.get(id=50)
some_post   = Post.objects.get(id=50)

The syntax is same as above the only difference being that the instead of add we use remove.

To get all objects in many to many filed we use .all() method on the field. See the example below,

some_author = Author.objects.get(id=50)
some_post   = Post.objects.get(id=50)
all_liked_post = some_author.liked_posts.all()

Filtering By Integers

You can also filter integer filed and it should be obvious by now, let’s see the examples and it should be clear and there is nothing fancy in it.

more_liked_posts = Post.objects.all(likes_count >= 500)
less_liked_posts = Post.objects.all(likes_count <= 500)
some_posts = Post.objects.all(likes_count = 500)

Using Order By

We can order our query results by using order_by method at the end of the query, let’s see an example,

posts = Post.objects.all().order_by('likes_count', '-created_at')
more_posts = Post.objects.all().order_by('likes_count', '-created_at')[:100]

We pass the field name in order_by() as string. The order by which the names of the fields are passed in order by are passed the they are ordered in the same way . It is useful when you want order results by more than field. We can also limit the results by using limit thing, I am not sure what to call it, this one [:100] .

Hope you guys like, if you share this it would be amazing and it would be appreciated a lot. It takes a lot of effort to write such articles so a share would be great.

Also check out my other articles. Hope you like them too. 😊

You may also like: