Reputation: 43
Help me please with my problem. I want to get objects sorted first by one filter and then by another filter.
How can I get objects with this ordering in 1 query to the DB (need for pagination)?
This example shows queryset without ordering:
rooms = Room.objects.filter(Q(name__icontains=search) | Q(owner__username__icontains=search))
I have the room model:
models.py
from django.db import models
from django.contrib.auth.models import User
class Room(models.Model):
name = models.CharField(max_length=150)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
views.py (my bad code)
class RoomListView(ListAPIView):
def get_queryset(self):
search = 'test' # for example
rooms1 = Room.objects.filter(owner__username__icontains=search)
rooms2 = Room.objects.filter(name__icontains=search)
return list(rooms1) + list(rooms2)
The wrong result: search = "test"
[
{
"id":1,
"name":"test",
"owner":{
"username":"user1"
}
},
{
"id":2,
"name":"room1",
"owner":{
"username":"test"
}
},
{
"id":3,
"name":"test2",
"owner":{
"username":"user2"
}
}
]
The correct result: search = "test"
[
{
"id":2,
"name":"room1",
"owner":{
"username":"test"
}
},
{
"id":1,
"name":"test",
"owner":{
"username":"user1"
}
},
{
"id":3,
"name":"test2",
"owner":{
"username":"user2"
}
}
]
How can I get objects with this ordering in 1 query to the DB (need for pagination)?
Upvotes: 2
Views: 2195
Reputation: 31
Use CASE WHEN expression and mark correct filter condition by integer. Pseudocode: case when username = test then 1 when room = test then 2 ... END "CASECOL" order by "CASECOL" ASC
Upvotes: 0
Reputation: 101
You can sort the columns by using order_by()
Example
# Sorting columns with id, name, username in dynamically
order_by_list = []
# sort by name
order_by_list.append('name')
# And second username sort along with name
order_by_list.append('owner__username')
Room.objects.filter(.....).order_by(*order_by_list)
Here, we can append
the column
names dynamically to order_by_list
Upvotes: 0
Reputation: 101
As I understand you want to filter and order the rows with multi columns
single
column sortingrooms = Room.objects.filter(Q(name__icontains=search) | Q(owner__username__icontains=search)).order_by('name')
multi
columns sortingHere, we can order the columns with owner_username
and same owner_username rows will be order_by with name
rooms = Room.objects.filter(Q(name__icontains=search) | Q(owner__username__icontains=search)).order_by('owner__username', 'name')
order_by()
# Sorting order will in the order of column_1, column_2, column_3
Room.objects.filter(.....).order_by('column_1', 'column_2', 'column_3)
Upvotes: 2